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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [sim/] [frv/] [memory.c] - Diff between revs 835 and 841

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

Rev 835 Rev 841
/* frv memory model.
/* frv memory model.
   Copyright (C) 1999, 2000, 2001, 2003, 2007, 2008, 2009, 2010
   Copyright (C) 1999, 2000, 2001, 2003, 2007, 2008, 2009, 2010
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
   Contributed by Red Hat
   Contributed by Red Hat
 
 
This file is part of the GNU simulators.
This file is part of the GNU simulators.
 
 
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 3 of the License, or
the Free Software Foundation; either version 3 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, see <http://www.gnu.org/licenses/>.  */
along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
#define WANT_CPU frvbf
#define WANT_CPU frvbf
#define WANT_CPU_FRVBF
#define WANT_CPU_FRVBF
 
 
#include "sim-main.h"
#include "sim-main.h"
#include "cgen-mem.h"
#include "cgen-mem.h"
#include "bfd.h"
#include "bfd.h"
 
 
/* Check for alignment and access restrictions.  Return the corrected address.
/* Check for alignment and access restrictions.  Return the corrected address.
 */
 */
static SI
static SI
fr400_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
fr400_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
{
{
  /* Check access restrictions for double word loads only.  */
  /* Check access restrictions for double word loads only.  */
  if (align_mask == 7)
  if (align_mask == 7)
    {
    {
      if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
      if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
        frv_queue_data_access_error_interrupt (current_cpu, address);
        frv_queue_data_access_error_interrupt (current_cpu, address);
    }
    }
  return address;
  return address;
}
}
 
 
static SI
static SI
fr500_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
fr500_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
{
{
  if (address & align_mask)
  if (address & align_mask)
    {
    {
      frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
      frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
      address &= ~align_mask;
      address &= ~align_mask;
    }
    }
 
 
  if ((USI)address >= 0xfeff0600 && (USI)address <= 0xfeff7fff
  if ((USI)address >= 0xfeff0600 && (USI)address <= 0xfeff7fff
      || (USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff)
      || (USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff)
    frv_queue_data_access_error_interrupt (current_cpu, address);
    frv_queue_data_access_error_interrupt (current_cpu, address);
 
 
  return address;
  return address;
}
}
 
 
static SI
static SI
fr550_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
fr550_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
{
{
  if ((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff
  if ((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff
      || (align_mask > 0x3
      || (align_mask > 0x3
          && ((USI)address >= 0xfeff0000 && (USI)address <= 0xfeffffff)))
          && ((USI)address >= 0xfeff0000 && (USI)address <= 0xfeffffff)))
    frv_queue_data_access_error_interrupt (current_cpu, address);
    frv_queue_data_access_error_interrupt (current_cpu, address);
 
 
  return address;
  return address;
}
}
 
 
static SI
static SI
check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask)
{
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  SIM_DESC sd = CPU_STATE (current_cpu);
  switch (STATE_ARCHITECTURE (sd)->mach)
  switch (STATE_ARCHITECTURE (sd)->mach)
    {
    {
    case bfd_mach_fr400:
    case bfd_mach_fr400:
    case bfd_mach_fr450:
    case bfd_mach_fr450:
      address = fr400_check_data_read_address (current_cpu, address,
      address = fr400_check_data_read_address (current_cpu, address,
                                               align_mask);
                                               align_mask);
      break;
      break;
    case bfd_mach_frvtomcat:
    case bfd_mach_frvtomcat:
    case bfd_mach_fr500:
    case bfd_mach_fr500:
    case bfd_mach_frv:
    case bfd_mach_frv:
      address = fr500_check_data_read_address (current_cpu, address,
      address = fr500_check_data_read_address (current_cpu, address,
                                               align_mask);
                                               align_mask);
      break;
      break;
    case bfd_mach_fr550:
    case bfd_mach_fr550:
      address = fr550_check_data_read_address (current_cpu, address,
      address = fr550_check_data_read_address (current_cpu, address,
                                               align_mask);
                                               align_mask);
      break;
      break;
    default:
    default:
      break;
      break;
    }
    }
 
 
  return address;
  return address;
}
}
 
 
static SI
static SI
fr400_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
fr400_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
{
{
  if (address & align_mask)
  if (address & align_mask)
    {
    {
      /* Make sure that this exception is not masked.  */
      /* Make sure that this exception is not masked.  */
      USI isr = GET_ISR ();
      USI isr = GET_ISR ();
      if (! GET_ISR_EMAM (isr))
      if (! GET_ISR_EMAM (isr))
        {
        {
          /* Bad alignment causes a data_access_error on fr400.  */
          /* Bad alignment causes a data_access_error on fr400.  */
          frv_queue_data_access_error_interrupt (current_cpu, address);
          frv_queue_data_access_error_interrupt (current_cpu, address);
        }
        }
      address &= ~align_mask;
      address &= ~align_mask;
    }
    }
  /* Nothing to check.  */
  /* Nothing to check.  */
  return address;
  return address;
}
}
 
 
static SI
static SI
fr500_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
fr500_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
{
{
  if ((USI)address >= 0xfe000000 && (USI)address <= 0xfe003fff
  if ((USI)address >= 0xfe000000 && (USI)address <= 0xfe003fff
      || (USI)address >= 0xfe004000 && (USI)address <= 0xfe3fffff
      || (USI)address >= 0xfe004000 && (USI)address <= 0xfe3fffff
      || (USI)address >= 0xfe400000 && (USI)address <= 0xfe403fff
      || (USI)address >= 0xfe400000 && (USI)address <= 0xfe403fff
      || (USI)address >= 0xfe404000 && (USI)address <= 0xfe7fffff)
      || (USI)address >= 0xfe404000 && (USI)address <= 0xfe7fffff)
    frv_queue_data_access_exception_interrupt (current_cpu);
    frv_queue_data_access_exception_interrupt (current_cpu);
 
 
  return address;
  return address;
}
}
 
 
static SI
static SI
fr550_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
fr550_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
{
{
  /* No alignment restrictions on fr550 */
  /* No alignment restrictions on fr550 */
 
 
  if ((USI)address >= 0xfe000000 && (USI)address <= 0xfe3fffff
  if ((USI)address >= 0xfe000000 && (USI)address <= 0xfe3fffff
      || (USI)address >= 0xfe408000 && (USI)address <= 0xfe7fffff)
      || (USI)address >= 0xfe408000 && (USI)address <= 0xfe7fffff)
    frv_queue_data_access_exception_interrupt (current_cpu);
    frv_queue_data_access_exception_interrupt (current_cpu);
  else
  else
    {
    {
      USI hsr0 = GET_HSR0 ();
      USI hsr0 = GET_HSR0 ();
      if (! GET_HSR0_RME (hsr0)
      if (! GET_HSR0_RME (hsr0)
          && (USI)address >= 0xfe400000 && (USI)address <= 0xfe407fff)
          && (USI)address >= 0xfe400000 && (USI)address <= 0xfe407fff)
        frv_queue_data_access_exception_interrupt (current_cpu);
        frv_queue_data_access_exception_interrupt (current_cpu);
    }
    }
 
 
  return address;
  return address;
}
}
 
 
static SI
static SI
check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask)
{
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  SIM_DESC sd = CPU_STATE (current_cpu);
  switch (STATE_ARCHITECTURE (sd)->mach)
  switch (STATE_ARCHITECTURE (sd)->mach)
    {
    {
    case bfd_mach_fr400:
    case bfd_mach_fr400:
    case bfd_mach_fr450:
    case bfd_mach_fr450:
      address = fr400_check_readwrite_address (current_cpu, address,
      address = fr400_check_readwrite_address (current_cpu, address,
                                                    align_mask);
                                                    align_mask);
      break;
      break;
    case bfd_mach_frvtomcat:
    case bfd_mach_frvtomcat:
    case bfd_mach_fr500:
    case bfd_mach_fr500:
    case bfd_mach_frv:
    case bfd_mach_frv:
      address = fr500_check_readwrite_address (current_cpu, address,
      address = fr500_check_readwrite_address (current_cpu, address,
                                                    align_mask);
                                                    align_mask);
      break;
      break;
    case bfd_mach_fr550:
    case bfd_mach_fr550:
      address = fr550_check_readwrite_address (current_cpu, address,
      address = fr550_check_readwrite_address (current_cpu, address,
                                               align_mask);
                                               align_mask);
      break;
      break;
    default:
    default:
      break;
      break;
    }
    }
 
 
  return address;
  return address;
}
}
 
 
static PCADDR
static PCADDR
fr400_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
fr400_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
                               int align_mask)
                               int align_mask)
{
{
  if (address & align_mask)
  if (address & align_mask)
    {
    {
      frv_queue_instruction_access_error_interrupt (current_cpu);
      frv_queue_instruction_access_error_interrupt (current_cpu);
      address &= ~align_mask;
      address &= ~align_mask;
    }
    }
  else if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
  else if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
    frv_queue_instruction_access_error_interrupt (current_cpu);
    frv_queue_instruction_access_error_interrupt (current_cpu);
 
 
  return address;
  return address;
}
}
 
 
static PCADDR
static PCADDR
fr500_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
fr500_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
                               int align_mask)
                               int align_mask)
{
{
  if (address & align_mask)
  if (address & align_mask)
    {
    {
      frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
      frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
      address &= ~align_mask;
      address &= ~align_mask;
    }
    }
 
 
  if ((USI)address >= 0xfeff0600 && (USI)address <= 0xfeff7fff
  if ((USI)address >= 0xfeff0600 && (USI)address <= 0xfeff7fff
      || (USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff)
      || (USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff)
    frv_queue_instruction_access_error_interrupt (current_cpu);
    frv_queue_instruction_access_error_interrupt (current_cpu);
  else if ((USI)address >= 0xfe004000 && (USI)address <= 0xfe3fffff
  else if ((USI)address >= 0xfe004000 && (USI)address <= 0xfe3fffff
           || (USI)address >= 0xfe400000 && (USI)address <= 0xfe403fff
           || (USI)address >= 0xfe400000 && (USI)address <= 0xfe403fff
           || (USI)address >= 0xfe404000 && (USI)address <= 0xfe7fffff)
           || (USI)address >= 0xfe404000 && (USI)address <= 0xfe7fffff)
    frv_queue_instruction_access_exception_interrupt (current_cpu);
    frv_queue_instruction_access_exception_interrupt (current_cpu);
  else
  else
    {
    {
      USI hsr0 = GET_HSR0 ();
      USI hsr0 = GET_HSR0 ();
      if (! GET_HSR0_RME (hsr0)
      if (! GET_HSR0_RME (hsr0)
          && (USI)address >= 0xfe000000 && (USI)address <= 0xfe003fff)
          && (USI)address >= 0xfe000000 && (USI)address <= 0xfe003fff)
        frv_queue_instruction_access_exception_interrupt (current_cpu);
        frv_queue_instruction_access_exception_interrupt (current_cpu);
    }
    }
 
 
  return address;
  return address;
}
}
 
 
static PCADDR
static PCADDR
fr550_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
fr550_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address,
                               int align_mask)
                               int align_mask)
{
{
  address &= ~align_mask;
  address &= ~align_mask;
 
 
  if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
  if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff)
    frv_queue_instruction_access_error_interrupt (current_cpu);
    frv_queue_instruction_access_error_interrupt (current_cpu);
  else if ((USI)address >= 0xfe008000 && (USI)address <= 0xfe7fffff)
  else if ((USI)address >= 0xfe008000 && (USI)address <= 0xfe7fffff)
    frv_queue_instruction_access_exception_interrupt (current_cpu);
    frv_queue_instruction_access_exception_interrupt (current_cpu);
  else
  else
    {
    {
      USI hsr0 = GET_HSR0 ();
      USI hsr0 = GET_HSR0 ();
      if (! GET_HSR0_RME (hsr0)
      if (! GET_HSR0_RME (hsr0)
          && (USI)address >= 0xfe000000 && (USI)address <= 0xfe007fff)
          && (USI)address >= 0xfe000000 && (USI)address <= 0xfe007fff)
        frv_queue_instruction_access_exception_interrupt (current_cpu);
        frv_queue_instruction_access_exception_interrupt (current_cpu);
    }
    }
 
 
  return address;
  return address;
}
}
 
 
static PCADDR
static PCADDR
check_insn_read_address (SIM_CPU *current_cpu, PCADDR address, int align_mask)
check_insn_read_address (SIM_CPU *current_cpu, PCADDR address, int align_mask)
{
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  SIM_DESC sd = CPU_STATE (current_cpu);
  switch (STATE_ARCHITECTURE (sd)->mach)
  switch (STATE_ARCHITECTURE (sd)->mach)
    {
    {
    case bfd_mach_fr400:
    case bfd_mach_fr400:
    case bfd_mach_fr450:
    case bfd_mach_fr450:
      address = fr400_check_insn_read_address (current_cpu, address,
      address = fr400_check_insn_read_address (current_cpu, address,
                                               align_mask);
                                               align_mask);
      break;
      break;
    case bfd_mach_frvtomcat:
    case bfd_mach_frvtomcat:
    case bfd_mach_fr500:
    case bfd_mach_fr500:
    case bfd_mach_frv:
    case bfd_mach_frv:
      address = fr500_check_insn_read_address (current_cpu, address,
      address = fr500_check_insn_read_address (current_cpu, address,
                                               align_mask);
                                               align_mask);
      break;
      break;
    case bfd_mach_fr550:
    case bfd_mach_fr550:
      address = fr550_check_insn_read_address (current_cpu, address,
      address = fr550_check_insn_read_address (current_cpu, address,
                                               align_mask);
                                               align_mask);
      break;
      break;
    default:
    default:
      break;
      break;
    }
    }
 
 
  return address;
  return address;
}
}
 
 
/* Memory reads.  */
/* Memory reads.  */
QI
QI
frvbf_read_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address)
frvbf_read_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address)
{
{
  USI hsr0 = GET_HSR0 ();
  USI hsr0 = GET_HSR0 ();
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
 
 
  /* Check for access exceptions.  */
  /* Check for access exceptions.  */
  address = check_data_read_address (current_cpu, address, 0);
  address = check_data_read_address (current_cpu, address, 0);
  address = check_readwrite_address (current_cpu, address, 0);
  address = check_readwrite_address (current_cpu, address, 0);
 
 
  /* If we need to count cycles, then the cache operation will be
  /* If we need to count cycles, then the cache operation will be
     initiated from the model profiling functions.
     initiated from the model profiling functions.
     See frvbf_model_....  */
     See frvbf_model_....  */
  if (model_insn)
  if (model_insn)
    {
    {
      CPU_LOAD_ADDRESS (current_cpu) = address;
      CPU_LOAD_ADDRESS (current_cpu) = address;
      CPU_LOAD_LENGTH (current_cpu) = 1;
      CPU_LOAD_LENGTH (current_cpu) = 1;
      CPU_LOAD_SIGNED (current_cpu) = 1;
      CPU_LOAD_SIGNED (current_cpu) = 1;
      return 0xb7; /* any random value */
      return 0xb7; /* any random value */
    }
    }
 
 
  if (GET_HSR0_DCE (hsr0))
  if (GET_HSR0_DCE (hsr0))
    {
    {
      int cycles;
      int cycles;
      cycles = frv_cache_read (cache, 0, address);
      cycles = frv_cache_read (cache, 0, address);
      if (cycles != 0)
      if (cycles != 0)
        return CACHE_RETURN_DATA (cache, 0, address, QI, 1);
        return CACHE_RETURN_DATA (cache, 0, address, QI, 1);
    }
    }
 
 
  return GETMEMQI (current_cpu, pc, address);
  return GETMEMQI (current_cpu, pc, address);
}
}
 
 
UQI
UQI
frvbf_read_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address)
frvbf_read_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address)
{
{
  USI hsr0 = GET_HSR0 ();
  USI hsr0 = GET_HSR0 ();
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
 
 
  /* Check for access exceptions.  */
  /* Check for access exceptions.  */
  address = check_data_read_address (current_cpu, address, 0);
  address = check_data_read_address (current_cpu, address, 0);
  address = check_readwrite_address (current_cpu, address, 0);
  address = check_readwrite_address (current_cpu, address, 0);
 
 
  /* If we need to count cycles, then the cache operation will be
  /* If we need to count cycles, then the cache operation will be
     initiated from the model profiling functions.
     initiated from the model profiling functions.
     See frvbf_model_....  */
     See frvbf_model_....  */
  if (model_insn)
  if (model_insn)
    {
    {
      CPU_LOAD_ADDRESS (current_cpu) = address;
      CPU_LOAD_ADDRESS (current_cpu) = address;
      CPU_LOAD_LENGTH (current_cpu) = 1;
      CPU_LOAD_LENGTH (current_cpu) = 1;
      CPU_LOAD_SIGNED (current_cpu) = 0;
      CPU_LOAD_SIGNED (current_cpu) = 0;
      return 0xb7; /* any random value */
      return 0xb7; /* any random value */
    }
    }
 
 
  if (GET_HSR0_DCE (hsr0))
  if (GET_HSR0_DCE (hsr0))
    {
    {
      int cycles;
      int cycles;
      cycles = frv_cache_read (cache, 0, address);
      cycles = frv_cache_read (cache, 0, address);
      if (cycles != 0)
      if (cycles != 0)
        return CACHE_RETURN_DATA (cache, 0, address, UQI, 1);
        return CACHE_RETURN_DATA (cache, 0, address, UQI, 1);
    }
    }
 
 
  return GETMEMUQI (current_cpu, pc, address);
  return GETMEMUQI (current_cpu, pc, address);
}
}
 
 
/* Read a HI which spans two cache lines */
/* Read a HI which spans two cache lines */
static HI
static HI
read_mem_unaligned_HI (SIM_CPU *current_cpu, IADDR pc, SI address)
read_mem_unaligned_HI (SIM_CPU *current_cpu, IADDR pc, SI address)
{
{
  HI value = frvbf_read_mem_QI (current_cpu, pc, address);
  HI value = frvbf_read_mem_QI (current_cpu, pc, address);
  value <<= 8;
  value <<= 8;
  value |= frvbf_read_mem_UQI (current_cpu, pc, address + 1);
  value |= frvbf_read_mem_UQI (current_cpu, pc, address + 1);
  return T2H_2 (value);
  return T2H_2 (value);
}
}
 
 
HI
HI
frvbf_read_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address)
frvbf_read_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address)
{
{
  USI hsr0;
  USI hsr0;
  FRV_CACHE *cache;
  FRV_CACHE *cache;
 
 
  /* Check for access exceptions.  */
  /* Check for access exceptions.  */
  address = check_data_read_address (current_cpu, address, 1);
  address = check_data_read_address (current_cpu, address, 1);
  address = check_readwrite_address (current_cpu, address, 1);
  address = check_readwrite_address (current_cpu, address, 1);
 
 
  /* If we need to count cycles, then the cache operation will be
  /* If we need to count cycles, then the cache operation will be
     initiated from the model profiling functions.
     initiated from the model profiling functions.
     See frvbf_model_....  */
     See frvbf_model_....  */
  hsr0 = GET_HSR0 ();
  hsr0 = GET_HSR0 ();
  cache = CPU_DATA_CACHE (current_cpu);
  cache = CPU_DATA_CACHE (current_cpu);
  if (model_insn)
  if (model_insn)
    {
    {
      CPU_LOAD_ADDRESS (current_cpu) = address;
      CPU_LOAD_ADDRESS (current_cpu) = address;
      CPU_LOAD_LENGTH (current_cpu) = 2;
      CPU_LOAD_LENGTH (current_cpu) = 2;
      CPU_LOAD_SIGNED (current_cpu) = 1;
      CPU_LOAD_SIGNED (current_cpu) = 1;
      return 0xb711; /* any random value */
      return 0xb711; /* any random value */
    }
    }
 
 
  if (GET_HSR0_DCE (hsr0))
  if (GET_HSR0_DCE (hsr0))
    {
    {
      int cycles;
      int cycles;
      /* Handle access which crosses cache line boundary */
      /* Handle access which crosses cache line boundary */
      SIM_DESC sd = CPU_STATE (current_cpu);
      SIM_DESC sd = CPU_STATE (current_cpu);
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
        {
        {
          if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
          if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
            return read_mem_unaligned_HI (current_cpu, pc, address);
            return read_mem_unaligned_HI (current_cpu, pc, address);
        }
        }
      cycles = frv_cache_read (cache, 0, address);
      cycles = frv_cache_read (cache, 0, address);
      if (cycles != 0)
      if (cycles != 0)
        return CACHE_RETURN_DATA (cache, 0, address, HI, 2);
        return CACHE_RETURN_DATA (cache, 0, address, HI, 2);
    }
    }
 
 
  return GETMEMHI (current_cpu, pc, address);
  return GETMEMHI (current_cpu, pc, address);
}
}
 
 
UHI
UHI
frvbf_read_mem_UHI (SIM_CPU *current_cpu, IADDR pc, SI address)
frvbf_read_mem_UHI (SIM_CPU *current_cpu, IADDR pc, SI address)
{
{
  USI hsr0;
  USI hsr0;
  FRV_CACHE *cache;
  FRV_CACHE *cache;
 
 
  /* Check for access exceptions.  */
  /* Check for access exceptions.  */
  address = check_data_read_address (current_cpu, address, 1);
  address = check_data_read_address (current_cpu, address, 1);
  address = check_readwrite_address (current_cpu, address, 1);
  address = check_readwrite_address (current_cpu, address, 1);
 
 
  /* If we need to count cycles, then the cache operation will be
  /* If we need to count cycles, then the cache operation will be
     initiated from the model profiling functions.
     initiated from the model profiling functions.
     See frvbf_model_....  */
     See frvbf_model_....  */
  hsr0 = GET_HSR0 ();
  hsr0 = GET_HSR0 ();
  cache = CPU_DATA_CACHE (current_cpu);
  cache = CPU_DATA_CACHE (current_cpu);
  if (model_insn)
  if (model_insn)
    {
    {
      CPU_LOAD_ADDRESS (current_cpu) = address;
      CPU_LOAD_ADDRESS (current_cpu) = address;
      CPU_LOAD_LENGTH (current_cpu) = 2;
      CPU_LOAD_LENGTH (current_cpu) = 2;
      CPU_LOAD_SIGNED (current_cpu) = 0;
      CPU_LOAD_SIGNED (current_cpu) = 0;
      return 0xb711; /* any random value */
      return 0xb711; /* any random value */
    }
    }
 
 
  if (GET_HSR0_DCE (hsr0))
  if (GET_HSR0_DCE (hsr0))
    {
    {
      int cycles;
      int cycles;
      /* Handle access which crosses cache line boundary */
      /* Handle access which crosses cache line boundary */
      SIM_DESC sd = CPU_STATE (current_cpu);
      SIM_DESC sd = CPU_STATE (current_cpu);
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
        {
        {
          if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
          if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
            return read_mem_unaligned_HI (current_cpu, pc, address);
            return read_mem_unaligned_HI (current_cpu, pc, address);
        }
        }
      cycles = frv_cache_read (cache, 0, address);
      cycles = frv_cache_read (cache, 0, address);
      if (cycles != 0)
      if (cycles != 0)
        return CACHE_RETURN_DATA (cache, 0, address, UHI, 2);
        return CACHE_RETURN_DATA (cache, 0, address, UHI, 2);
    }
    }
 
 
  return GETMEMUHI (current_cpu, pc, address);
  return GETMEMUHI (current_cpu, pc, address);
}
}
 
 
/* Read a SI which spans two cache lines */
/* Read a SI which spans two cache lines */
static SI
static SI
read_mem_unaligned_SI (SIM_CPU *current_cpu, IADDR pc, SI address)
read_mem_unaligned_SI (SIM_CPU *current_cpu, IADDR pc, SI address)
{
{
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
  unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
  unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
  char valarray[4];
  char valarray[4];
  SI SIvalue;
  SI SIvalue;
  HI HIvalue;
  HI HIvalue;
 
 
  switch (hi_len)
  switch (hi_len)
    {
    {
    case 1:
    case 1:
      valarray[0] = frvbf_read_mem_QI (current_cpu, pc, address);
      valarray[0] = frvbf_read_mem_QI (current_cpu, pc, address);
      SIvalue = frvbf_read_mem_SI (current_cpu, pc, address + 1);
      SIvalue = frvbf_read_mem_SI (current_cpu, pc, address + 1);
      SIvalue = H2T_4 (SIvalue);
      SIvalue = H2T_4 (SIvalue);
      memcpy (valarray + 1, (char*)&SIvalue, 3);
      memcpy (valarray + 1, (char*)&SIvalue, 3);
      break;
      break;
    case 2:
    case 2:
      HIvalue = frvbf_read_mem_HI (current_cpu, pc, address);
      HIvalue = frvbf_read_mem_HI (current_cpu, pc, address);
      HIvalue = H2T_2 (HIvalue);
      HIvalue = H2T_2 (HIvalue);
      memcpy (valarray, (char*)&HIvalue, 2);
      memcpy (valarray, (char*)&HIvalue, 2);
      HIvalue = frvbf_read_mem_HI (current_cpu, pc, address + 2);
      HIvalue = frvbf_read_mem_HI (current_cpu, pc, address + 2);
      HIvalue = H2T_2 (HIvalue);
      HIvalue = H2T_2 (HIvalue);
      memcpy (valarray + 2, (char*)&HIvalue, 2);
      memcpy (valarray + 2, (char*)&HIvalue, 2);
      break;
      break;
    case 3:
    case 3:
      SIvalue = frvbf_read_mem_SI (current_cpu, pc, address - 1);
      SIvalue = frvbf_read_mem_SI (current_cpu, pc, address - 1);
      SIvalue = H2T_4 (SIvalue);
      SIvalue = H2T_4 (SIvalue);
      memcpy (valarray, (char*)&SIvalue, 3);
      memcpy (valarray, (char*)&SIvalue, 3);
      valarray[3] = frvbf_read_mem_QI (current_cpu, pc, address + 3);
      valarray[3] = frvbf_read_mem_QI (current_cpu, pc, address + 3);
      break;
      break;
    default:
    default:
      abort (); /* can't happen */
      abort (); /* can't happen */
    }
    }
  return T2H_4 (*(SI*)valarray);
  return T2H_4 (*(SI*)valarray);
}
}
 
 
SI
SI
frvbf_read_mem_SI (SIM_CPU *current_cpu, IADDR pc, SI address)
frvbf_read_mem_SI (SIM_CPU *current_cpu, IADDR pc, SI address)
{
{
  FRV_CACHE *cache;
  FRV_CACHE *cache;
  USI hsr0;
  USI hsr0;
 
 
  /* Check for access exceptions.  */
  /* Check for access exceptions.  */
  address = check_data_read_address (current_cpu, address, 3);
  address = check_data_read_address (current_cpu, address, 3);
  address = check_readwrite_address (current_cpu, address, 3);
  address = check_readwrite_address (current_cpu, address, 3);
 
 
  hsr0 = GET_HSR0 ();
  hsr0 = GET_HSR0 ();
  cache = CPU_DATA_CACHE (current_cpu);
  cache = CPU_DATA_CACHE (current_cpu);
  /* If we need to count cycles, then the cache operation will be
  /* If we need to count cycles, then the cache operation will be
     initiated from the model profiling functions.
     initiated from the model profiling functions.
     See frvbf_model_....  */
     See frvbf_model_....  */
  if (model_insn)
  if (model_insn)
    {
    {
      CPU_LOAD_ADDRESS (current_cpu) = address;
      CPU_LOAD_ADDRESS (current_cpu) = address;
      CPU_LOAD_LENGTH (current_cpu) = 4;
      CPU_LOAD_LENGTH (current_cpu) = 4;
      return 0x37111319; /* any random value */
      return 0x37111319; /* any random value */
    }
    }
 
 
  if (GET_HSR0_DCE (hsr0))
  if (GET_HSR0_DCE (hsr0))
    {
    {
      int cycles;
      int cycles;
      /* Handle access which crosses cache line boundary */
      /* Handle access which crosses cache line boundary */
      SIM_DESC sd = CPU_STATE (current_cpu);
      SIM_DESC sd = CPU_STATE (current_cpu);
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
        {
        {
          if (DATA_CROSSES_CACHE_LINE (cache, address, 4))
          if (DATA_CROSSES_CACHE_LINE (cache, address, 4))
            return read_mem_unaligned_SI (current_cpu, pc, address);
            return read_mem_unaligned_SI (current_cpu, pc, address);
        }
        }
      cycles = frv_cache_read (cache, 0, address);
      cycles = frv_cache_read (cache, 0, address);
      if (cycles != 0)
      if (cycles != 0)
        return CACHE_RETURN_DATA (cache, 0, address, SI, 4);
        return CACHE_RETURN_DATA (cache, 0, address, SI, 4);
    }
    }
 
 
  return GETMEMSI (current_cpu, pc, address);
  return GETMEMSI (current_cpu, pc, address);
}
}
 
 
SI
SI
frvbf_read_mem_WI (SIM_CPU *current_cpu, IADDR pc, SI address)
frvbf_read_mem_WI (SIM_CPU *current_cpu, IADDR pc, SI address)
{
{
  return frvbf_read_mem_SI (current_cpu, pc, address);
  return frvbf_read_mem_SI (current_cpu, pc, address);
}
}
 
 
/* Read a SI which spans two cache lines */
/* Read a SI which spans two cache lines */
static DI
static DI
read_mem_unaligned_DI (SIM_CPU *current_cpu, IADDR pc, SI address)
read_mem_unaligned_DI (SIM_CPU *current_cpu, IADDR pc, SI address)
{
{
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
  unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
  unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
  DI value, value1;
  DI value, value1;
 
 
  switch (hi_len)
  switch (hi_len)
    {
    {
    case 1:
    case 1:
      value = frvbf_read_mem_QI (current_cpu, pc, address);
      value = frvbf_read_mem_QI (current_cpu, pc, address);
      value <<= 56;
      value <<= 56;
      value1 = frvbf_read_mem_DI (current_cpu, pc, address + 1);
      value1 = frvbf_read_mem_DI (current_cpu, pc, address + 1);
      value1 = H2T_8 (value1);
      value1 = H2T_8 (value1);
      value |= value1 & ((DI)0x00ffffff << 32);
      value |= value1 & ((DI)0x00ffffff << 32);
      value |= value1 & 0xffffffffu;
      value |= value1 & 0xffffffffu;
      break;
      break;
    case 2:
    case 2:
      value = frvbf_read_mem_HI (current_cpu, pc, address);
      value = frvbf_read_mem_HI (current_cpu, pc, address);
      value = H2T_2 (value);
      value = H2T_2 (value);
      value <<= 48;
      value <<= 48;
      value1 = frvbf_read_mem_DI (current_cpu, pc, address + 2);
      value1 = frvbf_read_mem_DI (current_cpu, pc, address + 2);
      value1 = H2T_8 (value1);
      value1 = H2T_8 (value1);
      value |= value1 & ((DI)0x0000ffff << 32);
      value |= value1 & ((DI)0x0000ffff << 32);
      value |= value1 & 0xffffffffu;
      value |= value1 & 0xffffffffu;
      break;
      break;
    case 3:
    case 3:
      value = frvbf_read_mem_SI (current_cpu, pc, address - 1);
      value = frvbf_read_mem_SI (current_cpu, pc, address - 1);
      value = H2T_4 (value);
      value = H2T_4 (value);
      value <<= 40;
      value <<= 40;
      value1 = frvbf_read_mem_DI (current_cpu, pc, address + 3);
      value1 = frvbf_read_mem_DI (current_cpu, pc, address + 3);
      value1 = H2T_8 (value1);
      value1 = H2T_8 (value1);
      value |= value1 & ((DI)0x000000ff << 32);
      value |= value1 & ((DI)0x000000ff << 32);
      value |= value1 & 0xffffffffu;
      value |= value1 & 0xffffffffu;
      break;
      break;
    case 4:
    case 4:
      value = frvbf_read_mem_SI (current_cpu, pc, address);
      value = frvbf_read_mem_SI (current_cpu, pc, address);
      value = H2T_4 (value);
      value = H2T_4 (value);
      value <<= 32;
      value <<= 32;
      value1 = frvbf_read_mem_SI (current_cpu, pc, address + 4);
      value1 = frvbf_read_mem_SI (current_cpu, pc, address + 4);
      value1 = H2T_4 (value1);
      value1 = H2T_4 (value1);
      value |= value1 & 0xffffffffu;
      value |= value1 & 0xffffffffu;
      break;
      break;
    case 5:
    case 5:
      value = frvbf_read_mem_DI (current_cpu, pc, address - 3);
      value = frvbf_read_mem_DI (current_cpu, pc, address - 3);
      value = H2T_8 (value);
      value = H2T_8 (value);
      value <<= 24;
      value <<= 24;
      value1 = frvbf_read_mem_SI (current_cpu, pc, address + 5);
      value1 = frvbf_read_mem_SI (current_cpu, pc, address + 5);
      value1 = H2T_4 (value1);
      value1 = H2T_4 (value1);
      value |= value1 & 0x00ffffff;
      value |= value1 & 0x00ffffff;
      break;
      break;
    case 6:
    case 6:
      value = frvbf_read_mem_DI (current_cpu, pc, address - 2);
      value = frvbf_read_mem_DI (current_cpu, pc, address - 2);
      value = H2T_8 (value);
      value = H2T_8 (value);
      value <<= 16;
      value <<= 16;
      value1 = frvbf_read_mem_HI (current_cpu, pc, address + 6);
      value1 = frvbf_read_mem_HI (current_cpu, pc, address + 6);
      value1 = H2T_2 (value1);
      value1 = H2T_2 (value1);
      value |= value1 & 0x0000ffff;
      value |= value1 & 0x0000ffff;
      break;
      break;
    case 7:
    case 7:
      value = frvbf_read_mem_DI (current_cpu, pc, address - 1);
      value = frvbf_read_mem_DI (current_cpu, pc, address - 1);
      value = H2T_8 (value);
      value = H2T_8 (value);
      value <<= 8;
      value <<= 8;
      value1 = frvbf_read_mem_QI (current_cpu, pc, address + 7);
      value1 = frvbf_read_mem_QI (current_cpu, pc, address + 7);
      value |= value1 & 0x000000ff;
      value |= value1 & 0x000000ff;
      break;
      break;
    default:
    default:
      abort (); /* can't happen */
      abort (); /* can't happen */
    }
    }
  return T2H_8 (value);
  return T2H_8 (value);
}
}
 
 
DI
DI
frvbf_read_mem_DI (SIM_CPU *current_cpu, IADDR pc, SI address)
frvbf_read_mem_DI (SIM_CPU *current_cpu, IADDR pc, SI address)
{
{
  USI hsr0;
  USI hsr0;
  FRV_CACHE *cache;
  FRV_CACHE *cache;
 
 
  /* Check for access exceptions.  */
  /* Check for access exceptions.  */
  address = check_data_read_address (current_cpu, address, 7);
  address = check_data_read_address (current_cpu, address, 7);
  address = check_readwrite_address (current_cpu, address, 7);
  address = check_readwrite_address (current_cpu, address, 7);
 
 
  /* If we need to count cycles, then the cache operation will be
  /* If we need to count cycles, then the cache operation will be
     initiated from the model profiling functions.
     initiated from the model profiling functions.
     See frvbf_model_....  */
     See frvbf_model_....  */
  hsr0 = GET_HSR0 ();
  hsr0 = GET_HSR0 ();
  cache = CPU_DATA_CACHE (current_cpu);
  cache = CPU_DATA_CACHE (current_cpu);
  if (model_insn)
  if (model_insn)
    {
    {
      CPU_LOAD_ADDRESS (current_cpu) = address;
      CPU_LOAD_ADDRESS (current_cpu) = address;
      CPU_LOAD_LENGTH (current_cpu) = 8;
      CPU_LOAD_LENGTH (current_cpu) = 8;
      return 0x37111319; /* any random value */
      return 0x37111319; /* any random value */
    }
    }
 
 
  if (GET_HSR0_DCE (hsr0))
  if (GET_HSR0_DCE (hsr0))
    {
    {
      int cycles;
      int cycles;
      /* Handle access which crosses cache line boundary */
      /* Handle access which crosses cache line boundary */
      SIM_DESC sd = CPU_STATE (current_cpu);
      SIM_DESC sd = CPU_STATE (current_cpu);
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
        {
        {
          if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
          if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
            return read_mem_unaligned_DI (current_cpu, pc, address);
            return read_mem_unaligned_DI (current_cpu, pc, address);
        }
        }
      cycles = frv_cache_read (cache, 0, address);
      cycles = frv_cache_read (cache, 0, address);
      if (cycles != 0)
      if (cycles != 0)
        return CACHE_RETURN_DATA (cache, 0, address, DI, 8);
        return CACHE_RETURN_DATA (cache, 0, address, DI, 8);
    }
    }
 
 
  return GETMEMDI (current_cpu, pc, address);
  return GETMEMDI (current_cpu, pc, address);
}
}
 
 
DF
DF
frvbf_read_mem_DF (SIM_CPU *current_cpu, IADDR pc, SI address)
frvbf_read_mem_DF (SIM_CPU *current_cpu, IADDR pc, SI address)
{
{
  USI hsr0;
  USI hsr0;
  FRV_CACHE *cache;
  FRV_CACHE *cache;
 
 
  /* Check for access exceptions.  */
  /* Check for access exceptions.  */
  address = check_data_read_address (current_cpu, address, 7);
  address = check_data_read_address (current_cpu, address, 7);
  address = check_readwrite_address (current_cpu, address, 7);
  address = check_readwrite_address (current_cpu, address, 7);
 
 
  /* If we need to count cycles, then the cache operation will be
  /* If we need to count cycles, then the cache operation will be
     initiated from the model profiling functions.
     initiated from the model profiling functions.
     See frvbf_model_....  */
     See frvbf_model_....  */
  hsr0 = GET_HSR0 ();
  hsr0 = GET_HSR0 ();
  cache = CPU_DATA_CACHE (current_cpu);
  cache = CPU_DATA_CACHE (current_cpu);
  if (model_insn)
  if (model_insn)
    {
    {
      CPU_LOAD_ADDRESS (current_cpu) = address;
      CPU_LOAD_ADDRESS (current_cpu) = address;
      CPU_LOAD_LENGTH (current_cpu) = 8;
      CPU_LOAD_LENGTH (current_cpu) = 8;
      return 0x37111319; /* any random value */
      return 0x37111319; /* any random value */
    }
    }
 
 
  if (GET_HSR0_DCE (hsr0))
  if (GET_HSR0_DCE (hsr0))
    {
    {
      int cycles;
      int cycles;
      /* Handle access which crosses cache line boundary */
      /* Handle access which crosses cache line boundary */
      SIM_DESC sd = CPU_STATE (current_cpu);
      SIM_DESC sd = CPU_STATE (current_cpu);
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
        {
        {
          if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
          if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
            return read_mem_unaligned_DI (current_cpu, pc, address);
            return read_mem_unaligned_DI (current_cpu, pc, address);
        }
        }
      cycles = frv_cache_read (cache, 0, address);
      cycles = frv_cache_read (cache, 0, address);
      if (cycles != 0)
      if (cycles != 0)
        return CACHE_RETURN_DATA (cache, 0, address, DF, 8);
        return CACHE_RETURN_DATA (cache, 0, address, DF, 8);
    }
    }
 
 
  return GETMEMDF (current_cpu, pc, address);
  return GETMEMDF (current_cpu, pc, address);
}
}
 
 
USI
USI
frvbf_read_imem_USI (SIM_CPU *current_cpu, PCADDR vpc)
frvbf_read_imem_USI (SIM_CPU *current_cpu, PCADDR vpc)
{
{
  USI hsr0;
  USI hsr0;
  vpc = check_insn_read_address (current_cpu, vpc, 3);
  vpc = check_insn_read_address (current_cpu, vpc, 3);
 
 
  hsr0 = GET_HSR0 ();
  hsr0 = GET_HSR0 ();
  if (GET_HSR0_ICE (hsr0))
  if (GET_HSR0_ICE (hsr0))
    {
    {
      FRV_CACHE *cache;
      FRV_CACHE *cache;
      USI value;
      USI value;
 
 
      /* We don't want this to show up in the cache statistics.  That read
      /* We don't want this to show up in the cache statistics.  That read
         is done in frvbf_simulate_insn_prefetch.  So read the cache or memory
         is done in frvbf_simulate_insn_prefetch.  So read the cache or memory
         passively here.  */
         passively here.  */
      cache = CPU_INSN_CACHE (current_cpu);
      cache = CPU_INSN_CACHE (current_cpu);
      if (frv_cache_read_passive_SI (cache, vpc, &value))
      if (frv_cache_read_passive_SI (cache, vpc, &value))
        return value;
        return value;
    }
    }
  return sim_core_read_unaligned_4 (current_cpu, vpc, read_map, vpc);
  return sim_core_read_unaligned_4 (current_cpu, vpc, read_map, vpc);
}
}
 
 
static SI
static SI
fr400_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
fr400_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
{
{
  if (align_mask == 7
  if (align_mask == 7
      && address >= 0xfe800000 && address <= 0xfeffffff)
      && address >= 0xfe800000 && address <= 0xfeffffff)
    frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
    frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
 
 
  return address;
  return address;
}
}
 
 
static SI
static SI
fr500_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
fr500_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
{
{
  if (address & align_mask)
  if (address & align_mask)
    {
    {
      struct frv_interrupt_queue_element *item =
      struct frv_interrupt_queue_element *item =
        frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
        frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
      /* Record the correct vliw slot with the interrupt.  */
      /* Record the correct vliw slot with the interrupt.  */
      if (item != NULL)
      if (item != NULL)
        item->slot = frv_interrupt_state.slot;
        item->slot = frv_interrupt_state.slot;
      address &= ~align_mask;
      address &= ~align_mask;
    }
    }
  if (address >= 0xfeff0600 && address <= 0xfeff7fff
  if (address >= 0xfeff0600 && address <= 0xfeff7fff
      || address >= 0xfe800000 && address <= 0xfefeffff)
      || address >= 0xfe800000 && address <= 0xfefeffff)
    frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
    frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
 
 
  return address;
  return address;
}
}
 
 
static SI
static SI
fr550_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
fr550_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
{
{
  if ((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff
  if ((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff
      || (align_mask > 0x3
      || (align_mask > 0x3
          && ((USI)address >= 0xfeff0000 && (USI)address <= 0xfeffffff)))
          && ((USI)address >= 0xfeff0000 && (USI)address <= 0xfeffffff)))
    frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
    frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR);
 
 
  return address;
  return address;
}
}
 
 
static SI
static SI
check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
check_write_address (SIM_CPU *current_cpu, SI address, int align_mask)
{
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  SIM_DESC sd = CPU_STATE (current_cpu);
  switch (STATE_ARCHITECTURE (sd)->mach)
  switch (STATE_ARCHITECTURE (sd)->mach)
    {
    {
    case bfd_mach_fr400:
    case bfd_mach_fr400:
    case bfd_mach_fr450:
    case bfd_mach_fr450:
      address = fr400_check_write_address (current_cpu, address, align_mask);
      address = fr400_check_write_address (current_cpu, address, align_mask);
      break;
      break;
    case bfd_mach_frvtomcat:
    case bfd_mach_frvtomcat:
    case bfd_mach_fr500:
    case bfd_mach_fr500:
    case bfd_mach_frv:
    case bfd_mach_frv:
      address = fr500_check_write_address (current_cpu, address, align_mask);
      address = fr500_check_write_address (current_cpu, address, align_mask);
      break;
      break;
    case bfd_mach_fr550:
    case bfd_mach_fr550:
      address = fr550_check_write_address (current_cpu, address, align_mask);
      address = fr550_check_write_address (current_cpu, address, align_mask);
      break;
      break;
    default:
    default:
      break;
      break;
    }
    }
  return address;
  return address;
}
}
 
 
void
void
frvbf_write_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address, QI value)
frvbf_write_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address, QI value)
{
{
  USI hsr0;
  USI hsr0;
  hsr0 = GET_HSR0 ();
  hsr0 = GET_HSR0 ();
  if (GET_HSR0_DCE (hsr0))
  if (GET_HSR0_DCE (hsr0))
    sim_queue_fn_mem_qi_write (current_cpu, frvbf_mem_set_QI, address, value);
    sim_queue_fn_mem_qi_write (current_cpu, frvbf_mem_set_QI, address, value);
  else
  else
    sim_queue_mem_qi_write (current_cpu, address, value);
    sim_queue_mem_qi_write (current_cpu, address, value);
  frv_set_write_queue_slot (current_cpu);
  frv_set_write_queue_slot (current_cpu);
}
}
 
 
void
void
frvbf_write_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address, UQI value)
frvbf_write_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address, UQI value)
{
{
  frvbf_write_mem_QI (current_cpu, pc, address, value);
  frvbf_write_mem_QI (current_cpu, pc, address, value);
}
}
 
 
void
void
frvbf_write_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
frvbf_write_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
{
{
  USI hsr0;
  USI hsr0;
  hsr0 = GET_HSR0 ();
  hsr0 = GET_HSR0 ();
  if (GET_HSR0_DCE (hsr0))
  if (GET_HSR0_DCE (hsr0))
    sim_queue_fn_mem_hi_write (current_cpu, frvbf_mem_set_HI, address, value);
    sim_queue_fn_mem_hi_write (current_cpu, frvbf_mem_set_HI, address, value);
  else
  else
    sim_queue_mem_hi_write (current_cpu, address, value);
    sim_queue_mem_hi_write (current_cpu, address, value);
  frv_set_write_queue_slot (current_cpu);
  frv_set_write_queue_slot (current_cpu);
}
}
 
 
void
void
frvbf_write_mem_UHI (SIM_CPU *current_cpu, IADDR pc, SI address, UHI value)
frvbf_write_mem_UHI (SIM_CPU *current_cpu, IADDR pc, SI address, UHI value)
{
{
  frvbf_write_mem_HI (current_cpu, pc, address, value);
  frvbf_write_mem_HI (current_cpu, pc, address, value);
}
}
 
 
void
void
frvbf_write_mem_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
frvbf_write_mem_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
{
{
  USI hsr0;
  USI hsr0;
  hsr0 = GET_HSR0 ();
  hsr0 = GET_HSR0 ();
  if (GET_HSR0_DCE (hsr0))
  if (GET_HSR0_DCE (hsr0))
    sim_queue_fn_mem_si_write (current_cpu, frvbf_mem_set_SI, address, value);
    sim_queue_fn_mem_si_write (current_cpu, frvbf_mem_set_SI, address, value);
  else
  else
    sim_queue_mem_si_write (current_cpu, address, value);
    sim_queue_mem_si_write (current_cpu, address, value);
  frv_set_write_queue_slot (current_cpu);
  frv_set_write_queue_slot (current_cpu);
}
}
 
 
void
void
frvbf_write_mem_WI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
frvbf_write_mem_WI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
{
{
  frvbf_write_mem_SI (current_cpu, pc, address, value);
  frvbf_write_mem_SI (current_cpu, pc, address, value);
}
}
 
 
void
void
frvbf_write_mem_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
frvbf_write_mem_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
{
{
  USI hsr0;
  USI hsr0;
  hsr0 = GET_HSR0 ();
  hsr0 = GET_HSR0 ();
  if (GET_HSR0_DCE (hsr0))
  if (GET_HSR0_DCE (hsr0))
    sim_queue_fn_mem_di_write (current_cpu, frvbf_mem_set_DI, address, value);
    sim_queue_fn_mem_di_write (current_cpu, frvbf_mem_set_DI, address, value);
  else
  else
    sim_queue_mem_di_write (current_cpu, address, value);
    sim_queue_mem_di_write (current_cpu, address, value);
  frv_set_write_queue_slot (current_cpu);
  frv_set_write_queue_slot (current_cpu);
}
}
 
 
void
void
frvbf_write_mem_DF (SIM_CPU *current_cpu, IADDR pc, SI address, DF value)
frvbf_write_mem_DF (SIM_CPU *current_cpu, IADDR pc, SI address, DF value)
{
{
  USI hsr0;
  USI hsr0;
  hsr0 = GET_HSR0 ();
  hsr0 = GET_HSR0 ();
  if (GET_HSR0_DCE (hsr0))
  if (GET_HSR0_DCE (hsr0))
    sim_queue_fn_mem_df_write (current_cpu, frvbf_mem_set_DF, address, value);
    sim_queue_fn_mem_df_write (current_cpu, frvbf_mem_set_DF, address, value);
  else
  else
    sim_queue_mem_df_write (current_cpu, address, value);
    sim_queue_mem_df_write (current_cpu, address, value);
  frv_set_write_queue_slot (current_cpu);
  frv_set_write_queue_slot (current_cpu);
}
}
 
 
/* Memory writes.  These do the actual writing through the cache.  */
/* Memory writes.  These do the actual writing through the cache.  */
void
void
frvbf_mem_set_QI (SIM_CPU *current_cpu, IADDR pc, SI address, QI value)
frvbf_mem_set_QI (SIM_CPU *current_cpu, IADDR pc, SI address, QI value)
{
{
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
 
 
  /* Check for access errors.  */
  /* Check for access errors.  */
  address = check_write_address (current_cpu, address, 0);
  address = check_write_address (current_cpu, address, 0);
  address = check_readwrite_address (current_cpu, address, 0);
  address = check_readwrite_address (current_cpu, address, 0);
 
 
  /* If we need to count cycles, then submit the write request to the cache
  /* If we need to count cycles, then submit the write request to the cache
     and let it prioritize the request.  Otherwise perform the write now.  */
     and let it prioritize the request.  Otherwise perform the write now.  */
  if (model_insn)
  if (model_insn)
    {
    {
      int slot = UNIT_I0;
      int slot = UNIT_I0;
      frv_cache_request_store (cache, address, slot, (char *)&value,
      frv_cache_request_store (cache, address, slot, (char *)&value,
                               sizeof (value));
                               sizeof (value));
    }
    }
  else
  else
    frv_cache_write (cache, address, (char *)&value, sizeof (value));
    frv_cache_write (cache, address, (char *)&value, sizeof (value));
}
}
 
 
/* Write a HI which spans two cache lines */
/* Write a HI which spans two cache lines */
static void
static void
mem_set_unaligned_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
mem_set_unaligned_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
{
{
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
  /* value is already in target byte order */
  /* value is already in target byte order */
  frv_cache_write (cache, address, (char *)&value, 1);
  frv_cache_write (cache, address, (char *)&value, 1);
  frv_cache_write (cache, address + 1, ((char *)&value + 1), 1);
  frv_cache_write (cache, address + 1, ((char *)&value + 1), 1);
}
}
 
 
void
void
frvbf_mem_set_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
frvbf_mem_set_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value)
{
{
  FRV_CACHE *cache;
  FRV_CACHE *cache;
 
 
  /* Check for access errors.  */
  /* Check for access errors.  */
  address = check_write_address (current_cpu, address, 1);
  address = check_write_address (current_cpu, address, 1);
  address = check_readwrite_address (current_cpu, address, 1);
  address = check_readwrite_address (current_cpu, address, 1);
 
 
  /* If we need to count cycles, then submit the write request to the cache
  /* If we need to count cycles, then submit the write request to the cache
     and let it prioritize the request.  Otherwise perform the write now.  */
     and let it prioritize the request.  Otherwise perform the write now.  */
  value = H2T_2 (value);
  value = H2T_2 (value);
  cache = CPU_DATA_CACHE (current_cpu);
  cache = CPU_DATA_CACHE (current_cpu);
  if (model_insn)
  if (model_insn)
    {
    {
      int slot = UNIT_I0;
      int slot = UNIT_I0;
      frv_cache_request_store (cache, address, slot,
      frv_cache_request_store (cache, address, slot,
                               (char *)&value, sizeof (value));
                               (char *)&value, sizeof (value));
    }
    }
  else
  else
    {
    {
      /* Handle access which crosses cache line boundary */
      /* Handle access which crosses cache line boundary */
      SIM_DESC sd = CPU_STATE (current_cpu);
      SIM_DESC sd = CPU_STATE (current_cpu);
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
        {
        {
          if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
          if (DATA_CROSSES_CACHE_LINE (cache, address, 2))
            {
            {
              mem_set_unaligned_HI (current_cpu, pc, address, value);
              mem_set_unaligned_HI (current_cpu, pc, address, value);
              return;
              return;
            }
            }
        }
        }
      frv_cache_write (cache, address, (char *)&value, sizeof (value));
      frv_cache_write (cache, address, (char *)&value, sizeof (value));
    }
    }
}
}
 
 
/* Write a SI which spans two cache lines */
/* Write a SI which spans two cache lines */
static void
static void
mem_set_unaligned_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
mem_set_unaligned_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
{
{
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
  unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
  unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
  /* value is already in target byte order */
  /* value is already in target byte order */
  frv_cache_write (cache, address, (char *)&value, hi_len);
  frv_cache_write (cache, address, (char *)&value, hi_len);
  frv_cache_write (cache, address + hi_len, (char *)&value + hi_len, 4 - hi_len);
  frv_cache_write (cache, address + hi_len, (char *)&value + hi_len, 4 - hi_len);
}
}
 
 
void
void
frvbf_mem_set_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
frvbf_mem_set_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value)
{
{
  FRV_CACHE *cache;
  FRV_CACHE *cache;
 
 
  /* Check for access errors.  */
  /* Check for access errors.  */
  address = check_write_address (current_cpu, address, 3);
  address = check_write_address (current_cpu, address, 3);
  address = check_readwrite_address (current_cpu, address, 3);
  address = check_readwrite_address (current_cpu, address, 3);
 
 
  /* If we need to count cycles, then submit the write request to the cache
  /* If we need to count cycles, then submit the write request to the cache
     and let it prioritize the request.  Otherwise perform the write now.  */
     and let it prioritize the request.  Otherwise perform the write now.  */
  cache = CPU_DATA_CACHE (current_cpu);
  cache = CPU_DATA_CACHE (current_cpu);
  value = H2T_4 (value);
  value = H2T_4 (value);
  if (model_insn)
  if (model_insn)
    {
    {
      int slot = UNIT_I0;
      int slot = UNIT_I0;
      frv_cache_request_store (cache, address, slot,
      frv_cache_request_store (cache, address, slot,
                               (char *)&value, sizeof (value));
                               (char *)&value, sizeof (value));
    }
    }
  else
  else
    {
    {
      /* Handle access which crosses cache line boundary */
      /* Handle access which crosses cache line boundary */
      SIM_DESC sd = CPU_STATE (current_cpu);
      SIM_DESC sd = CPU_STATE (current_cpu);
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
        {
        {
          if (DATA_CROSSES_CACHE_LINE (cache, address, 4))
          if (DATA_CROSSES_CACHE_LINE (cache, address, 4))
            {
            {
              mem_set_unaligned_SI (current_cpu, pc, address, value);
              mem_set_unaligned_SI (current_cpu, pc, address, value);
              return;
              return;
            }
            }
        }
        }
      frv_cache_write (cache, address, (char *)&value, sizeof (value));
      frv_cache_write (cache, address, (char *)&value, sizeof (value));
    }
    }
}
}
 
 
/* Write a DI which spans two cache lines */
/* Write a DI which spans two cache lines */
static void
static void
mem_set_unaligned_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
mem_set_unaligned_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
{
{
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
  FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
  unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
  unsigned hi_len = cache->line_size - (address & (cache->line_size - 1));
  /* value is already in target byte order */
  /* value is already in target byte order */
  frv_cache_write (cache, address, (char *)&value, hi_len);
  frv_cache_write (cache, address, (char *)&value, hi_len);
  frv_cache_write (cache, address + hi_len, (char *)&value + hi_len, 8 - hi_len);
  frv_cache_write (cache, address + hi_len, (char *)&value + hi_len, 8 - hi_len);
}
}
 
 
void
void
frvbf_mem_set_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
frvbf_mem_set_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value)
{
{
  FRV_CACHE *cache;
  FRV_CACHE *cache;
 
 
  /* Check for access errors.  */
  /* Check for access errors.  */
  address = check_write_address (current_cpu, address, 7);
  address = check_write_address (current_cpu, address, 7);
  address = check_readwrite_address (current_cpu, address, 7);
  address = check_readwrite_address (current_cpu, address, 7);
 
 
  /* If we need to count cycles, then submit the write request to the cache
  /* If we need to count cycles, then submit the write request to the cache
     and let it prioritize the request.  Otherwise perform the write now.  */
     and let it prioritize the request.  Otherwise perform the write now.  */
  value = H2T_8 (value);
  value = H2T_8 (value);
  cache = CPU_DATA_CACHE (current_cpu);
  cache = CPU_DATA_CACHE (current_cpu);
  if (model_insn)
  if (model_insn)
    {
    {
      int slot = UNIT_I0;
      int slot = UNIT_I0;
      frv_cache_request_store (cache, address, slot,
      frv_cache_request_store (cache, address, slot,
                               (char *)&value, sizeof (value));
                               (char *)&value, sizeof (value));
    }
    }
  else
  else
    {
    {
      /* Handle access which crosses cache line boundary */
      /* Handle access which crosses cache line boundary */
      SIM_DESC sd = CPU_STATE (current_cpu);
      SIM_DESC sd = CPU_STATE (current_cpu);
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
        {
        {
          if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
          if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
            {
            {
              mem_set_unaligned_DI (current_cpu, pc, address, value);
              mem_set_unaligned_DI (current_cpu, pc, address, value);
              return;
              return;
            }
            }
        }
        }
      frv_cache_write (cache, address, (char *)&value, sizeof (value));
      frv_cache_write (cache, address, (char *)&value, sizeof (value));
    }
    }
}
}
 
 
void
void
frvbf_mem_set_DF (SIM_CPU *current_cpu, IADDR pc, SI address, DF value)
frvbf_mem_set_DF (SIM_CPU *current_cpu, IADDR pc, SI address, DF value)
{
{
  FRV_CACHE *cache;
  FRV_CACHE *cache;
 
 
  /* Check for access errors.  */
  /* Check for access errors.  */
  address = check_write_address (current_cpu, address, 7);
  address = check_write_address (current_cpu, address, 7);
  address = check_readwrite_address (current_cpu, address, 7);
  address = check_readwrite_address (current_cpu, address, 7);
 
 
  /* If we need to count cycles, then submit the write request to the cache
  /* If we need to count cycles, then submit the write request to the cache
     and let it prioritize the request.  Otherwise perform the write now.  */
     and let it prioritize the request.  Otherwise perform the write now.  */
  value = H2T_8 (value);
  value = H2T_8 (value);
  cache = CPU_DATA_CACHE (current_cpu);
  cache = CPU_DATA_CACHE (current_cpu);
  if (model_insn)
  if (model_insn)
    {
    {
      int slot = UNIT_I0;
      int slot = UNIT_I0;
      frv_cache_request_store (cache, address, slot,
      frv_cache_request_store (cache, address, slot,
                               (char *)&value, sizeof (value));
                               (char *)&value, sizeof (value));
    }
    }
  else
  else
    {
    {
      /* Handle access which crosses cache line boundary */
      /* Handle access which crosses cache line boundary */
      SIM_DESC sd = CPU_STATE (current_cpu);
      SIM_DESC sd = CPU_STATE (current_cpu);
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550)
        {
        {
          if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
          if (DATA_CROSSES_CACHE_LINE (cache, address, 8))
            {
            {
              mem_set_unaligned_DI (current_cpu, pc, address, value);
              mem_set_unaligned_DI (current_cpu, pc, address, value);
              return;
              return;
            }
            }
        }
        }
      frv_cache_write (cache, address, (char *)&value, sizeof (value));
      frv_cache_write (cache, address, (char *)&value, sizeof (value));
    }
    }
}
}
 
 
void
void
frvbf_mem_set_XI (SIM_CPU *current_cpu, IADDR pc, SI address, SI *value)
frvbf_mem_set_XI (SIM_CPU *current_cpu, IADDR pc, SI address, SI *value)
{
{
  int i;
  int i;
  FRV_CACHE *cache;
  FRV_CACHE *cache;
 
 
  /* Check for access errors.  */
  /* Check for access errors.  */
  address = check_write_address (current_cpu, address, 0xf);
  address = check_write_address (current_cpu, address, 0xf);
  address = check_readwrite_address (current_cpu, address, 0xf);
  address = check_readwrite_address (current_cpu, address, 0xf);
 
 
  /* TODO -- reverse word order as well?  */
  /* TODO -- reverse word order as well?  */
  for (i = 0; i < 4; ++i)
  for (i = 0; i < 4; ++i)
    value[i] = H2T_4 (value[i]);
    value[i] = H2T_4 (value[i]);
 
 
  /* If we need to count cycles, then submit the write request to the cache
  /* If we need to count cycles, then submit the write request to the cache
     and let it prioritize the request.  Otherwise perform the write now.  */
     and let it prioritize the request.  Otherwise perform the write now.  */
  cache = CPU_DATA_CACHE (current_cpu);
  cache = CPU_DATA_CACHE (current_cpu);
  if (model_insn)
  if (model_insn)
    {
    {
      int slot = UNIT_I0;
      int slot = UNIT_I0;
      frv_cache_request_store (cache, address, slot, (char*)value, 16);
      frv_cache_request_store (cache, address, slot, (char*)value, 16);
    }
    }
  else
  else
    frv_cache_write (cache, address, (char*)value, 16);
    frv_cache_write (cache, address, (char*)value, 16);
}
}
 
 
/* Record the current VLIW slot on the element at the top of the write queue.
/* Record the current VLIW slot on the element at the top of the write queue.
*/
*/
void
void
frv_set_write_queue_slot (SIM_CPU *current_cpu)
frv_set_write_queue_slot (SIM_CPU *current_cpu)
{
{
  FRV_VLIW *vliw = CPU_VLIW (current_cpu);
  FRV_VLIW *vliw = CPU_VLIW (current_cpu);
  int slot = vliw->next_slot - 1;
  int slot = vliw->next_slot - 1;
  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (current_cpu);
  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (current_cpu);
  int ix = CGEN_WRITE_QUEUE_INDEX (q) - 1;
  int ix = CGEN_WRITE_QUEUE_INDEX (q) - 1;
  CGEN_WRITE_QUEUE_ELEMENT *item = CGEN_WRITE_QUEUE_ELEMENT (q, ix);
  CGEN_WRITE_QUEUE_ELEMENT *item = CGEN_WRITE_QUEUE_ELEMENT (q, ix);
  CGEN_WRITE_QUEUE_ELEMENT_PIPE (item) = (*vliw->current_vliw)[slot];
  CGEN_WRITE_QUEUE_ELEMENT_PIPE (item) = (*vliw->current_vliw)[slot];
}
}
 
 

powered by: WebSVN 2.1.0

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