14e98e3e1Schristos /* frv simulator support code 2*854b025fSchristos Copyright (C) 1999-2024 Free Software Foundation, Inc. 34e98e3e1Schristos Contributed by Red Hat. 44e98e3e1Schristos 54e98e3e1Schristos This file is part of the GNU simulators. 64e98e3e1Schristos 74e98e3e1Schristos This program is free software; you can redistribute it and/or modify 84e98e3e1Schristos it under the terms of the GNU General Public License as published by 94e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or 104e98e3e1Schristos (at your option) any later version. 114e98e3e1Schristos 124e98e3e1Schristos This program is distributed in the hope that it will be useful, 134e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 144e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 154e98e3e1Schristos GNU General Public License for more details. 164e98e3e1Schristos 174e98e3e1Schristos You should have received a copy of the GNU General Public License 184e98e3e1Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 194e98e3e1Schristos 204b169a6bSchristos /* This must come before any other includes. */ 214b169a6bSchristos #include "defs.h" 224b169a6bSchristos 234e98e3e1Schristos #define WANT_CPU 244e98e3e1Schristos #define WANT_CPU_FRVBF 254e98e3e1Schristos 264e98e3e1Schristos #include "sim-main.h" 274e98e3e1Schristos #include "bfd.h" 284b169a6bSchristos #include "cgen-mem.h" 294e98e3e1Schristos 304e98e3e1Schristos /* Initialize the frv simulator. */ 314e98e3e1Schristos void 324e98e3e1Schristos frv_initialize (SIM_CPU *current_cpu, SIM_DESC sd) 334e98e3e1Schristos { 344e98e3e1Schristos FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu); 354e98e3e1Schristos PROFILE_DATA *p = CPU_PROFILE_DATA (current_cpu); 364e98e3e1Schristos FRV_CACHE *insn_cache = CPU_INSN_CACHE (current_cpu); 374e98e3e1Schristos FRV_CACHE *data_cache = CPU_DATA_CACHE (current_cpu); 384e98e3e1Schristos int insn_cache_enabled = CACHE_INITIALIZED (insn_cache); 394e98e3e1Schristos int data_cache_enabled = CACHE_INITIALIZED (data_cache); 404e98e3e1Schristos USI hsr0; 414e98e3e1Schristos 424e98e3e1Schristos /* Initialize the register control information first since some of the 434e98e3e1Schristos register values are used in further configuration. */ 444e98e3e1Schristos frv_register_control_init (current_cpu); 454e98e3e1Schristos 464e98e3e1Schristos /* We need to ensure that the caches are initialized even if they are not 474e98e3e1Schristos initially enabled (via commandline) because they can be enabled by 484e98e3e1Schristos software. */ 494e98e3e1Schristos if (! insn_cache_enabled) 504e98e3e1Schristos frv_cache_init (current_cpu, CPU_INSN_CACHE (current_cpu)); 514e98e3e1Schristos if (! data_cache_enabled) 524e98e3e1Schristos frv_cache_init (current_cpu, CPU_DATA_CACHE (current_cpu)); 534e98e3e1Schristos 544e98e3e1Schristos /* Set the default cpu frequency if it has not been set on the command 554e98e3e1Schristos line. */ 564e98e3e1Schristos if (PROFILE_CPU_FREQ (p) == 0) 574e98e3e1Schristos PROFILE_CPU_FREQ (p) = 266000000; /* 266MHz */ 584e98e3e1Schristos 594e98e3e1Schristos /* Allocate one cache line of memory containing the address of the reset 604e98e3e1Schristos register Use the largest of the insn cache line size and the data cache 614e98e3e1Schristos line size. */ 624e98e3e1Schristos { 634e98e3e1Schristos int addr = RSTR_ADDRESS; 644e98e3e1Schristos void *aligned_buffer; 654e98e3e1Schristos int bytes; 664e98e3e1Schristos 674e98e3e1Schristos if (CPU_INSN_CACHE (current_cpu)->line_size 684e98e3e1Schristos > CPU_DATA_CACHE (current_cpu)->line_size) 694e98e3e1Schristos bytes = CPU_INSN_CACHE (current_cpu)->line_size; 704e98e3e1Schristos else 714e98e3e1Schristos bytes = CPU_DATA_CACHE (current_cpu)->line_size; 724e98e3e1Schristos 734e98e3e1Schristos /* 'bytes' is a power of 2. Calculate the starting address of the 744e98e3e1Schristos cache line. */ 754e98e3e1Schristos addr &= ~(bytes - 1); 764e98e3e1Schristos aligned_buffer = zalloc (bytes); /* clear */ 774e98e3e1Schristos sim_core_attach (sd, NULL, 0, access_read_write, 0, addr, bytes, 784e98e3e1Schristos 0, NULL, aligned_buffer); 794e98e3e1Schristos } 804e98e3e1Schristos 814e98e3e1Schristos PROFILE_INFO_CPU_CALLBACK(p) = frv_profile_info; 824e98e3e1Schristos ps->insn_fetch_address = -1; 834e98e3e1Schristos ps->branch_address = -1; 844e98e3e1Schristos 854e98e3e1Schristos cgen_init_accurate_fpu (current_cpu, CGEN_CPU_FPU (current_cpu), 864e98e3e1Schristos frvbf_fpu_error); 874e98e3e1Schristos 884e98e3e1Schristos /* Now perform power-on reset. */ 894e98e3e1Schristos frv_power_on_reset (current_cpu); 904e98e3e1Schristos 914e98e3e1Schristos /* Make sure that HSR0.ICE and HSR0.DCE are set properly. */ 924e98e3e1Schristos hsr0 = GET_HSR0 (); 934e98e3e1Schristos if (insn_cache_enabled) 944e98e3e1Schristos SET_HSR0_ICE (hsr0); 954e98e3e1Schristos else 964e98e3e1Schristos CLEAR_HSR0_ICE (hsr0); 974e98e3e1Schristos if (data_cache_enabled) 984e98e3e1Schristos SET_HSR0_DCE (hsr0); 994e98e3e1Schristos else 1004e98e3e1Schristos CLEAR_HSR0_DCE (hsr0); 1014e98e3e1Schristos SET_HSR0 (hsr0); 1024e98e3e1Schristos } 1034e98e3e1Schristos 1044e98e3e1Schristos /* Initialize the frv simulator. */ 1054e98e3e1Schristos void 1064e98e3e1Schristos frv_term (SIM_DESC sd) 1074e98e3e1Schristos { 1084e98e3e1Schristos /* If the timer is enabled, and model profiling was not originally enabled, 1094e98e3e1Schristos then turn it off again. This is the only place we can currently gain 1104e98e3e1Schristos control to do this. */ 1114e98e3e1Schristos if (frv_interrupt_state.timer.enabled && ! frv_save_profile_model_p) 112ba340e45Schristos sim_profile_set_option (sd, "-model", PROFILE_MODEL_IDX, "0"); 1134e98e3e1Schristos } 1144e98e3e1Schristos 1154e98e3e1Schristos /* Perform a power on reset. */ 1164e98e3e1Schristos void 1174e98e3e1Schristos frv_power_on_reset (SIM_CPU *cpu) 1184e98e3e1Schristos { 1194e98e3e1Schristos /* GR, FR and CPR registers are undefined at initialization time. */ 1204e98e3e1Schristos frv_initialize_spr (cpu); 1214e98e3e1Schristos /* Initialize the RSTR register (in memory). */ 1224e98e3e1Schristos if (frv_cache_enabled (CPU_DATA_CACHE (cpu))) 1234e98e3e1Schristos frvbf_mem_set_SI (cpu, CPU_PC_GET (cpu), RSTR_ADDRESS, RSTR_INITIAL_VALUE); 1244e98e3e1Schristos else 1254e98e3e1Schristos SETMEMSI (cpu, CPU_PC_GET (cpu), RSTR_ADDRESS, RSTR_INITIAL_VALUE); 1264e98e3e1Schristos } 1274e98e3e1Schristos 1284e98e3e1Schristos /* Perform a hardware reset. */ 1294e98e3e1Schristos void 1304e98e3e1Schristos frv_hardware_reset (SIM_CPU *cpu) 1314e98e3e1Schristos { 1324e98e3e1Schristos /* GR, FR and CPR registers are undefined at hardware reset. */ 1334e98e3e1Schristos frv_initialize_spr (cpu); 1344e98e3e1Schristos /* Reset the RSTR register (in memory). */ 1354e98e3e1Schristos if (frv_cache_enabled (CPU_DATA_CACHE (cpu))) 1364e98e3e1Schristos frvbf_mem_set_SI (cpu, CPU_PC_GET (cpu), RSTR_ADDRESS, RSTR_HARDWARE_RESET); 1374e98e3e1Schristos else 1384e98e3e1Schristos SETMEMSI (cpu, CPU_PC_GET (cpu), RSTR_ADDRESS, RSTR_HARDWARE_RESET); 1394e98e3e1Schristos /* Reset the insn and data caches. */ 1404e98e3e1Schristos frv_cache_invalidate_all (CPU_INSN_CACHE (cpu), 0/* no flush */); 1414e98e3e1Schristos frv_cache_invalidate_all (CPU_DATA_CACHE (cpu), 0/* no flush */); 1424e98e3e1Schristos } 1434e98e3e1Schristos 1444e98e3e1Schristos /* Perform a software reset. */ 1454e98e3e1Schristos void 1464e98e3e1Schristos frv_software_reset (SIM_CPU *cpu) 1474e98e3e1Schristos { 1484e98e3e1Schristos /* GR, FR and CPR registers are undefined at software reset. */ 1494e98e3e1Schristos frv_reset_spr (cpu); 1504e98e3e1Schristos /* Reset the RSTR register (in memory). */ 1514e98e3e1Schristos if (frv_cache_enabled (CPU_DATA_CACHE (cpu))) 1524e98e3e1Schristos frvbf_mem_set_SI (cpu, CPU_PC_GET (cpu), RSTR_ADDRESS, RSTR_SOFTWARE_RESET); 1534e98e3e1Schristos else 1544e98e3e1Schristos SETMEMSI (cpu, CPU_PC_GET (cpu), RSTR_ADDRESS, RSTR_SOFTWARE_RESET); 1554e98e3e1Schristos } 156