OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [gdb-5.0/] [sim/] [ppc/] [cpu.c] - Diff between revs 579 and 1765

Only display areas with differences | Details | Blame | View Log

Rev 579 Rev 1765
/*  This file is part of the program psim.
/*  This file is part of the program psim.
 
 
    Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
    Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
 
 
    This program is free software; you can redistribute it and/or modify
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    (at your option) any later version.
 
 
    This program is distributed in the hope that it will be useful,
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    GNU General Public License for more details.
 
 
    You should have received a copy of the GNU General Public License
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 
    */
    */
 
 
 
 
#ifndef _CPU_C_
#ifndef _CPU_C_
#define _CPU_C_
#define _CPU_C_
 
 
#include <setjmp.h>
#include <setjmp.h>
 
 
#include "cpu.h"
#include "cpu.h"
#include "idecode.h"
#include "idecode.h"
 
 
#ifdef HAVE_STRING_H
#ifdef HAVE_STRING_H
#include <string.h>
#include <string.h>
#else
#else
#ifdef HAVE_STRINGS_H
#ifdef HAVE_STRINGS_H
#include <strings.h>
#include <strings.h>
#endif
#endif
#endif
#endif
 
 
struct _cpu {
struct _cpu {
 
 
  /* the registers */
  /* the registers */
  registers regs;
  registers regs;
 
 
  /* current instruction address */
  /* current instruction address */
  unsigned_word program_counter;
  unsigned_word program_counter;
 
 
  /* the memory maps */
  /* the memory maps */
  core *physical; /* all of memory */
  core *physical; /* all of memory */
  vm *virtual;
  vm *virtual;
  vm_instruction_map *instruction_map; /* instructions */
  vm_instruction_map *instruction_map; /* instructions */
  vm_data_map *data_map; /* data */
  vm_data_map *data_map; /* data */
 
 
  /* the system this processor is contained within */
  /* the system this processor is contained within */
  cpu_mon *monitor;
  cpu_mon *monitor;
  os_emul *os_emulation;
  os_emul *os_emulation;
  psim *system;
  psim *system;
  event_queue *events;
  event_queue *events;
  int cpu_nr;
  int cpu_nr;
 
 
  /* Current CPU model information */
  /* Current CPU model information */
  model_data *model_ptr;
  model_data *model_ptr;
 
 
#if WITH_IDECODE_CACHE_SIZE
#if WITH_IDECODE_CACHE_SIZE
  /* a cache to store cracked instructions */
  /* a cache to store cracked instructions */
  idecode_cache icache[WITH_IDECODE_CACHE_SIZE];
  idecode_cache icache[WITH_IDECODE_CACHE_SIZE];
#endif
#endif
 
 
  /* any interrupt state */
  /* any interrupt state */
  interrupts ints;
  interrupts ints;
 
 
  /* address reservation: keep the physical address and the contents
  /* address reservation: keep the physical address and the contents
     of memory at that address */
     of memory at that address */
  memory_reservation reservation;
  memory_reservation reservation;
 
 
  /* offset from event time to this cpu's idea of the local time */
  /* offset from event time to this cpu's idea of the local time */
  signed64 time_base_local_time;
  signed64 time_base_local_time;
  signed64 decrementer_local_time;
  signed64 decrementer_local_time;
  event_entry_tag decrementer_event;
  event_entry_tag decrementer_event;
 
 
};
};
 
 
INLINE_CPU\
INLINE_CPU\
(cpu *)
(cpu *)
cpu_create(psim *system,
cpu_create(psim *system,
           core *memory,
           core *memory,
           cpu_mon *monitor,
           cpu_mon *monitor,
           os_emul *os_emulation,
           os_emul *os_emulation,
           int cpu_nr)
           int cpu_nr)
{
{
  cpu *processor = ZALLOC(cpu);
  cpu *processor = ZALLOC(cpu);
 
 
  /* create the virtual memory map from the core */
  /* create the virtual memory map from the core */
  processor->physical = memory;
  processor->physical = memory;
  processor->virtual = vm_create(memory);
  processor->virtual = vm_create(memory);
  processor->instruction_map = vm_create_instruction_map(processor->virtual);
  processor->instruction_map = vm_create_instruction_map(processor->virtual);
  processor->data_map = vm_create_data_map(processor->virtual);
  processor->data_map = vm_create_data_map(processor->virtual);
 
 
  if (CURRENT_MODEL_ISSUE > 0)
  if (CURRENT_MODEL_ISSUE > 0)
    processor->model_ptr = model_create (processor);
    processor->model_ptr = model_create (processor);
 
 
  /* link back to core system */
  /* link back to core system */
  processor->system = system;
  processor->system = system;
  processor->events = psim_event_queue(system);
  processor->events = psim_event_queue(system);
  processor->cpu_nr = cpu_nr;
  processor->cpu_nr = cpu_nr;
  processor->monitor = monitor;
  processor->monitor = monitor;
  processor->os_emulation = os_emulation;
  processor->os_emulation = os_emulation;
 
 
  return processor;
  return processor;
}
}
 
 
 
 
INLINE_CPU\
INLINE_CPU\
(void)
(void)
cpu_init(cpu *processor)
cpu_init(cpu *processor)
{
{
  memset(&processor->regs, 0, sizeof(processor->regs));
  memset(&processor->regs, 0, sizeof(processor->regs));
  /* vm init is delayed until after the device tree has been init as
  /* vm init is delayed until after the device tree has been init as
     the devices may further init the cpu */
     the devices may further init the cpu */
  if (CURRENT_MODEL_ISSUE > 0)
  if (CURRENT_MODEL_ISSUE > 0)
    model_init (processor->model_ptr);
    model_init (processor->model_ptr);
}
}
 
 
 
 
/* find ones way home */
/* find ones way home */
 
 
INLINE_CPU\
INLINE_CPU\
(psim *)
(psim *)
cpu_system(cpu *processor)
cpu_system(cpu *processor)
{
{
  return processor->system;
  return processor->system;
}
}
 
 
INLINE_CPU\
INLINE_CPU\
(int)
(int)
cpu_nr(cpu *processor)
cpu_nr(cpu *processor)
{
{
  return processor->cpu_nr;
  return processor->cpu_nr;
}
}
 
 
INLINE_CPU\
INLINE_CPU\
(cpu_mon *)
(cpu_mon *)
cpu_monitor(cpu *processor)
cpu_monitor(cpu *processor)
{
{
  return processor->monitor;
  return processor->monitor;
}
}
 
 
INLINE_CPU\
INLINE_CPU\
(os_emul *)
(os_emul *)
cpu_os_emulation(cpu *processor)
cpu_os_emulation(cpu *processor)
{
{
  return processor->os_emulation;
  return processor->os_emulation;
}
}
 
 
INLINE_CPU\
INLINE_CPU\
(model_data *)
(model_data *)
cpu_model(cpu *processor)
cpu_model(cpu *processor)
{
{
  return processor->model_ptr;
  return processor->model_ptr;
}
}
 
 
 
 
/* program counter manipulation */
/* program counter manipulation */
 
 
INLINE_CPU\
INLINE_CPU\
(void)
(void)
cpu_set_program_counter(cpu *processor,
cpu_set_program_counter(cpu *processor,
                        unsigned_word new_program_counter)
                        unsigned_word new_program_counter)
{
{
  processor->program_counter = new_program_counter;
  processor->program_counter = new_program_counter;
}
}
 
 
INLINE_CPU\
INLINE_CPU\
(unsigned_word)
(unsigned_word)
cpu_get_program_counter(cpu *processor)
cpu_get_program_counter(cpu *processor)
{
{
  return processor->program_counter;
  return processor->program_counter;
}
}
 
 
 
 
INLINE_CPU\
INLINE_CPU\
(void)
(void)
cpu_restart(cpu *processor,
cpu_restart(cpu *processor,
            unsigned_word nia)
            unsigned_word nia)
{
{
  ASSERT(processor != NULL);
  ASSERT(processor != NULL);
  cpu_set_program_counter(processor, nia);
  cpu_set_program_counter(processor, nia);
  psim_restart(processor->system, processor->cpu_nr);
  psim_restart(processor->system, processor->cpu_nr);
}
}
 
 
INLINE_CPU\
INLINE_CPU\
(void)
(void)
cpu_halt(cpu *processor,
cpu_halt(cpu *processor,
         unsigned_word nia,
         unsigned_word nia,
         stop_reason reason,
         stop_reason reason,
         int signal)
         int signal)
{
{
  ASSERT(processor != NULL);
  ASSERT(processor != NULL);
  if (CURRENT_MODEL_ISSUE > 0)
  if (CURRENT_MODEL_ISSUE > 0)
    model_halt(processor->model_ptr);
    model_halt(processor->model_ptr);
  cpu_set_program_counter(processor, nia);
  cpu_set_program_counter(processor, nia);
  psim_halt(processor->system, processor->cpu_nr, reason, signal);
  psim_halt(processor->system, processor->cpu_nr, reason, signal);
}
}
 
 
EXTERN_CPU\
EXTERN_CPU\
(void)
(void)
cpu_error(cpu *processor,
cpu_error(cpu *processor,
          unsigned_word cia,
          unsigned_word cia,
          const char *fmt,
          const char *fmt,
          ...)
          ...)
{
{
  char message[1024];
  char message[1024];
  va_list ap;
  va_list ap;
 
 
  /* format the message */
  /* format the message */
  va_start(ap, fmt);
  va_start(ap, fmt);
  vsprintf(message, fmt, ap);
  vsprintf(message, fmt, ap);
  va_end(ap);
  va_end(ap);
 
 
  /* sanity check */
  /* sanity check */
  if (strlen(message) >= sizeof(message))
  if (strlen(message) >= sizeof(message))
    error("cpu_error: buffer overflow");
    error("cpu_error: buffer overflow");
 
 
  if (processor != NULL) {
  if (processor != NULL) {
    printf_filtered("cpu %d, cia 0x%lx: %s\n",
    printf_filtered("cpu %d, cia 0x%lx: %s\n",
                    processor->cpu_nr + 1, (unsigned long)cia, message);
                    processor->cpu_nr + 1, (unsigned long)cia, message);
    cpu_halt(processor, cia, was_signalled, -1);
    cpu_halt(processor, cia, was_signalled, -1);
  }
  }
  else {
  else {
    error("cpu: %s", message);
    error("cpu: %s", message);
  }
  }
}
}
 
 
 
 
/* The processors local concept of time */
/* The processors local concept of time */
 
 
INLINE_CPU\
INLINE_CPU\
(signed64)
(signed64)
cpu_get_time_base(cpu *processor)
cpu_get_time_base(cpu *processor)
{
{
  return (event_queue_time(processor->events)
  return (event_queue_time(processor->events)
          - processor->time_base_local_time);
          - processor->time_base_local_time);
}
}
 
 
INLINE_CPU\
INLINE_CPU\
(void)
(void)
cpu_set_time_base(cpu *processor,
cpu_set_time_base(cpu *processor,
                  signed64 time_base)
                  signed64 time_base)
{
{
  processor->time_base_local_time = (event_queue_time(processor->events)
  processor->time_base_local_time = (event_queue_time(processor->events)
                                     - time_base);
                                     - time_base);
}
}
 
 
INLINE_CPU\
INLINE_CPU\
(signed32)
(signed32)
cpu_get_decrementer(cpu *processor)
cpu_get_decrementer(cpu *processor)
{
{
  return (processor->decrementer_local_time
  return (processor->decrementer_local_time
          - event_queue_time(processor->events));
          - event_queue_time(processor->events));
}
}
 
 
STATIC_INLINE_CPU\
STATIC_INLINE_CPU\
(void)
(void)
cpu_decrement_event(void *data)
cpu_decrement_event(void *data)
{
{
  cpu *processor = (cpu*)data;
  cpu *processor = (cpu*)data;
  processor->decrementer_event = NULL;
  processor->decrementer_event = NULL;
  decrementer_interrupt(processor);
  decrementer_interrupt(processor);
}
}
 
 
INLINE_CPU\
INLINE_CPU\
(void)
(void)
cpu_set_decrementer(cpu *processor,
cpu_set_decrementer(cpu *processor,
                    signed32 decrementer)
                    signed32 decrementer)
{
{
  signed64 old_decrementer = cpu_get_decrementer(processor);
  signed64 old_decrementer = cpu_get_decrementer(processor);
  event_queue_deschedule(processor->events, processor->decrementer_event);
  event_queue_deschedule(processor->events, processor->decrementer_event);
  processor->decrementer_event = NULL;
  processor->decrementer_event = NULL;
  processor->decrementer_local_time = (event_queue_time(processor->events)
  processor->decrementer_local_time = (event_queue_time(processor->events)
                                       + decrementer);
                                       + decrementer);
  if (decrementer < 0 && old_decrementer >= 0)
  if (decrementer < 0 && old_decrementer >= 0)
    /* A decrementer interrupt occures if the sign of the decrement
    /* A decrementer interrupt occures if the sign of the decrement
       register is changed from positive to negative by the load
       register is changed from positive to negative by the load
       instruction */
       instruction */
    decrementer_interrupt(processor);
    decrementer_interrupt(processor);
  else if (decrementer >= 0)
  else if (decrementer >= 0)
    processor->decrementer_event = event_queue_schedule(processor->events,
    processor->decrementer_event = event_queue_schedule(processor->events,
                                                        decrementer,
                                                        decrementer,
                                                        cpu_decrement_event,
                                                        cpu_decrement_event,
                                                        processor);
                                                        processor);
}
}
 
 
 
 
#if WITH_IDECODE_CACHE_SIZE
#if WITH_IDECODE_CACHE_SIZE
/* allow access to the cpu's instruction cache */
/* allow access to the cpu's instruction cache */
INLINE_CPU\
INLINE_CPU\
(idecode_cache *)
(idecode_cache *)
cpu_icache_entry(cpu *processor,
cpu_icache_entry(cpu *processor,
                 unsigned_word cia)
                 unsigned_word cia)
{
{
  return &processor->icache[cia / 4 % WITH_IDECODE_CACHE_SIZE];
  return &processor->icache[cia / 4 % WITH_IDECODE_CACHE_SIZE];
}
}
 
 
 
 
INLINE_CPU\
INLINE_CPU\
(void)
(void)
cpu_flush_icache(cpu *processor)
cpu_flush_icache(cpu *processor)
{
{
  int i;
  int i;
  /* force all addresses to 0xff... so that they never hit */
  /* force all addresses to 0xff... so that they never hit */
  for (i = 0; i < WITH_IDECODE_CACHE_SIZE; i++)
  for (i = 0; i < WITH_IDECODE_CACHE_SIZE; i++)
    processor->icache[i].address = MASK(0, 63);
    processor->icache[i].address = MASK(0, 63);
}
}
#endif
#endif
 
 
 
 
/* address map revelation */
/* address map revelation */
 
 
INLINE_CPU\
INLINE_CPU\
(vm_instruction_map *)
(vm_instruction_map *)
cpu_instruction_map(cpu *processor)
cpu_instruction_map(cpu *processor)
{
{
  return processor->instruction_map;
  return processor->instruction_map;
}
}
 
 
INLINE_CPU\
INLINE_CPU\
(vm_data_map *)
(vm_data_map *)
cpu_data_map(cpu *processor)
cpu_data_map(cpu *processor)
{
{
  return processor->data_map;
  return processor->data_map;
}
}
 
 
INLINE_CPU\
INLINE_CPU\
(void)
(void)
cpu_page_tlb_invalidate_entry(cpu *processor,
cpu_page_tlb_invalidate_entry(cpu *processor,
                              unsigned_word ea)
                              unsigned_word ea)
{
{
  vm_page_tlb_invalidate_entry(processor->virtual, ea);
  vm_page_tlb_invalidate_entry(processor->virtual, ea);
}
}
 
 
INLINE_CPU\
INLINE_CPU\
(void)
(void)
cpu_page_tlb_invalidate_all(cpu *processor)
cpu_page_tlb_invalidate_all(cpu *processor)
{
{
  vm_page_tlb_invalidate_all(processor->virtual);
  vm_page_tlb_invalidate_all(processor->virtual);
}
}
 
 
 
 
/* interrupt access */
/* interrupt access */
 
 
INLINE_CPU\
INLINE_CPU\
(interrupts *)
(interrupts *)
cpu_interrupts(cpu *processor)
cpu_interrupts(cpu *processor)
{
{
  return &processor->ints;
  return &processor->ints;
}
}
 
 
 
 
 
 
/* reservation access */
/* reservation access */
 
 
INLINE_CPU\
INLINE_CPU\
(memory_reservation *)
(memory_reservation *)
cpu_reservation(cpu *processor)
cpu_reservation(cpu *processor)
{
{
  return &processor->reservation;
  return &processor->reservation;
}
}
 
 
 
 
/* register access */
/* register access */
 
 
INLINE_CPU\
INLINE_CPU\
(registers *)
(registers *)
cpu_registers(cpu *processor)
cpu_registers(cpu *processor)
{
{
  return &processor->regs;
  return &processor->regs;
}
}
 
 
INLINE_CPU\
INLINE_CPU\
(void)
(void)
cpu_synchronize_context(cpu *processor,
cpu_synchronize_context(cpu *processor,
                        unsigned_word cia)
                        unsigned_word cia)
{
{
#if (WITH_IDECODE_CACHE_SIZE)
#if (WITH_IDECODE_CACHE_SIZE)
  /* kill of the cache */
  /* kill of the cache */
  cpu_flush_icache(processor);
  cpu_flush_icache(processor);
#endif
#endif
 
 
  /* update virtual memory */
  /* update virtual memory */
  vm_synchronize_context(processor->virtual,
  vm_synchronize_context(processor->virtual,
                         processor->regs.spr,
                         processor->regs.spr,
                         processor->regs.sr,
                         processor->regs.sr,
                         processor->regs.msr,
                         processor->regs.msr,
                         processor, cia);
                         processor, cia);
}
}
 
 
 
 
/* might again be useful one day */
/* might again be useful one day */
 
 
INLINE_CPU\
INLINE_CPU\
(void)
(void)
cpu_print_info(cpu *processor, int verbose)
cpu_print_info(cpu *processor, int verbose)
{
{
}
}
 
 
#endif /* _CPU_C_ */
#endif /* _CPU_C_ */
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.