📄 memory.c
字号:
/* frv memory model. Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc. Contributed by Red HatThis file is part of the GNU simulators.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public License alongwith this program; if not, write to the Free Software Foundation, Inc.,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#define WANT_CPU frvbf#define WANT_CPU_FRVBF#include "sim-main.h"#include "cgen-mem.h"#include "bfd.h"/* Check for alignment and access restrictions. Return the corrected address. */static SIfr400_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask){ /* Check access restrictions for double word loads only. */ if (align_mask == 7) { if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff) frv_queue_data_access_error_interrupt (current_cpu, address); } return address;}static SIfr500_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask){ if (address & align_mask) { frv_queue_mem_address_not_aligned_interrupt (current_cpu, address); address &= ~align_mask; } if ((USI)address >= 0xfeff0600 && (USI)address <= 0xfeff7fff || (USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff) frv_queue_data_access_error_interrupt (current_cpu, address); return address;}static SIfr550_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask){ if ((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff || (align_mask > 0x3 && ((USI)address >= 0xfeff0000 && (USI)address <= 0xfeffffff))) frv_queue_data_access_error_interrupt (current_cpu, address); return address;}static SIcheck_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask){ SIM_DESC sd = CPU_STATE (current_cpu); switch (STATE_ARCHITECTURE (sd)->mach) { case bfd_mach_fr400: case bfd_mach_fr450: address = fr400_check_data_read_address (current_cpu, address, align_mask); break; case bfd_mach_frvtomcat: case bfd_mach_fr500: case bfd_mach_frv: address = fr500_check_data_read_address (current_cpu, address, align_mask); break; case bfd_mach_fr550: address = fr550_check_data_read_address (current_cpu, address, align_mask); break; default: break; } return address;}static SIfr400_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask){ if (address & align_mask) { /* Make sure that this exception is not masked. */ USI isr = GET_ISR (); if (! GET_ISR_EMAM (isr)) { /* Bad alignment causes a data_access_error on fr400. */ frv_queue_data_access_error_interrupt (current_cpu, address); } address &= ~align_mask; } /* Nothing to check. */ return address;}static SIfr500_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask){ if ((USI)address >= 0xfe000000 && (USI)address <= 0xfe003fff || (USI)address >= 0xfe004000 && (USI)address <= 0xfe3fffff || (USI)address >= 0xfe400000 && (USI)address <= 0xfe403fff || (USI)address >= 0xfe404000 && (USI)address <= 0xfe7fffff) frv_queue_data_access_exception_interrupt (current_cpu); return address;}static SIfr550_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask){ /* No alignment restrictions on fr550 */ if ((USI)address >= 0xfe000000 && (USI)address <= 0xfe3fffff || (USI)address >= 0xfe408000 && (USI)address <= 0xfe7fffff) frv_queue_data_access_exception_interrupt (current_cpu); else { USI hsr0 = GET_HSR0 (); if (! GET_HSR0_RME (hsr0) && (USI)address >= 0xfe400000 && (USI)address <= 0xfe407fff) frv_queue_data_access_exception_interrupt (current_cpu); } return address;}static SIcheck_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask){ SIM_DESC sd = CPU_STATE (current_cpu); switch (STATE_ARCHITECTURE (sd)->mach) { case bfd_mach_fr400: case bfd_mach_fr450: address = fr400_check_readwrite_address (current_cpu, address, align_mask); break; case bfd_mach_frvtomcat: case bfd_mach_fr500: case bfd_mach_frv: address = fr500_check_readwrite_address (current_cpu, address, align_mask); break; case bfd_mach_fr550: address = fr550_check_readwrite_address (current_cpu, address, align_mask); break; default: break; } return address;}static PCADDRfr400_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address, int align_mask){ if (address & align_mask) { frv_queue_instruction_access_error_interrupt (current_cpu); address &= ~align_mask; } else if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff) frv_queue_instruction_access_error_interrupt (current_cpu); return address;}static PCADDRfr500_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address, int align_mask){ if (address & align_mask) { frv_queue_mem_address_not_aligned_interrupt (current_cpu, address); address &= ~align_mask; } if ((USI)address >= 0xfeff0600 && (USI)address <= 0xfeff7fff || (USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff) frv_queue_instruction_access_error_interrupt (current_cpu); else if ((USI)address >= 0xfe004000 && (USI)address <= 0xfe3fffff || (USI)address >= 0xfe400000 && (USI)address <= 0xfe403fff || (USI)address >= 0xfe404000 && (USI)address <= 0xfe7fffff) frv_queue_instruction_access_exception_interrupt (current_cpu); else { USI hsr0 = GET_HSR0 (); if (! GET_HSR0_RME (hsr0) && (USI)address >= 0xfe000000 && (USI)address <= 0xfe003fff) frv_queue_instruction_access_exception_interrupt (current_cpu); } return address;}static PCADDRfr550_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address, int align_mask){ address &= ~align_mask; if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff) frv_queue_instruction_access_error_interrupt (current_cpu); else if ((USI)address >= 0xfe008000 && (USI)address <= 0xfe7fffff) frv_queue_instruction_access_exception_interrupt (current_cpu); else { USI hsr0 = GET_HSR0 (); if (! GET_HSR0_RME (hsr0) && (USI)address >= 0xfe000000 && (USI)address <= 0xfe007fff) frv_queue_instruction_access_exception_interrupt (current_cpu); } return address;}static PCADDRcheck_insn_read_address (SIM_CPU *current_cpu, PCADDR address, int align_mask){ SIM_DESC sd = CPU_STATE (current_cpu); switch (STATE_ARCHITECTURE (sd)->mach) { case bfd_mach_fr400: case bfd_mach_fr450: address = fr400_check_insn_read_address (current_cpu, address, align_mask); break; case bfd_mach_frvtomcat: case bfd_mach_fr500: case bfd_mach_frv: address = fr500_check_insn_read_address (current_cpu, address, align_mask); break; case bfd_mach_fr550: address = fr550_check_insn_read_address (current_cpu, address, align_mask); break; default: break; } return address;}/* Memory reads. */QIfrvbf_read_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address){ USI hsr0 = GET_HSR0 (); FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); /* Check for access exceptions. */ address = check_data_read_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 initiated from the model profiling functions. See frvbf_model_.... */ if (model_insn) { CPU_LOAD_ADDRESS (current_cpu) = address; CPU_LOAD_LENGTH (current_cpu) = 1; CPU_LOAD_SIGNED (current_cpu) = 1; return 0xb7; /* any random value */ } if (GET_HSR0_DCE (hsr0)) { int cycles; cycles = frv_cache_read (cache, 0, address); if (cycles != 0) return CACHE_RETURN_DATA (cache, 0, address, QI, 1); } return GETMEMQI (current_cpu, pc, address);}UQIfrvbf_read_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address){ USI hsr0 = GET_HSR0 (); FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); /* Check for access exceptions. */ address = check_data_read_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 initiated from the model profiling functions. See frvbf_model_.... */ if (model_insn) { CPU_LOAD_ADDRESS (current_cpu) = address; CPU_LOAD_LENGTH (current_cpu) = 1; CPU_LOAD_SIGNED (current_cpu) = 0; return 0xb7; /* any random value */ } if (GET_HSR0_DCE (hsr0)) { int cycles; cycles = frv_cache_read (cache, 0, address); if (cycles != 0) return CACHE_RETURN_DATA (cache, 0, address, UQI, 1); } return GETMEMUQI (current_cpu, pc, address);}/* Read a HI which spans two cache lines */static HIread_mem_unaligned_HI (SIM_CPU *current_cpu, IADDR pc, SI address){ HI value = frvbf_read_mem_QI (current_cpu, pc, address); value <<= 8; value |= frvbf_read_mem_UQI (current_cpu, pc, address + 1); return T2H_2 (value);}HIfrvbf_read_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address){ USI hsr0; FRV_CACHE *cache; /* Check for access exceptions. */ address = check_data_read_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 initiated from the model profiling functions.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -