1 1.1 christos /* frv memory model. 2 1.1.1.10 christos Copyright (C) 1999-2024 Free Software Foundation, Inc. 3 1.1 christos Contributed by Red Hat 4 1.1 christos 5 1.1 christos This file is part of the GNU simulators. 6 1.1 christos 7 1.1 christos This program is free software; you can redistribute it and/or modify 8 1.1 christos it under the terms of the GNU General Public License as published by 9 1.1 christos the Free Software Foundation; either version 3 of the License, or 10 1.1 christos (at your option) any later version. 11 1.1 christos 12 1.1 christos This program is distributed in the hope that it will be useful, 13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 1.1 christos GNU General Public License for more details. 16 1.1 christos 17 1.1 christos You should have received a copy of the GNU General Public License 18 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 1.1 christos 20 1.1.1.9 christos /* This must come before any other includes. */ 21 1.1.1.9 christos #include "defs.h" 22 1.1.1.9 christos 23 1.1 christos #define WANT_CPU frvbf 24 1.1 christos #define WANT_CPU_FRVBF 25 1.1 christos 26 1.1 christos #include "sim-main.h" 27 1.1 christos #include "cgen-mem.h" 28 1.1 christos #include "bfd.h" 29 1.1.1.9 christos #include <stdlib.h> 30 1.1 christos 31 1.1 christos /* Check for alignment and access restrictions. Return the corrected address. 32 1.1 christos */ 33 1.1 christos static SI 34 1.1 christos fr400_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask) 35 1.1 christos { 36 1.1 christos /* Check access restrictions for double word loads only. */ 37 1.1 christos if (align_mask == 7) 38 1.1 christos { 39 1.1 christos if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff) 40 1.1 christos frv_queue_data_access_error_interrupt (current_cpu, address); 41 1.1 christos } 42 1.1 christos return address; 43 1.1 christos } 44 1.1 christos 45 1.1 christos static SI 46 1.1 christos fr500_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask) 47 1.1 christos { 48 1.1 christos if (address & align_mask) 49 1.1 christos { 50 1.1 christos frv_queue_mem_address_not_aligned_interrupt (current_cpu, address); 51 1.1 christos address &= ~align_mask; 52 1.1 christos } 53 1.1 christos 54 1.1.1.9 christos if (((USI)address >= 0xfeff0600 && (USI)address <= 0xfeff7fff) 55 1.1.1.9 christos || ((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff)) 56 1.1 christos frv_queue_data_access_error_interrupt (current_cpu, address); 57 1.1 christos 58 1.1 christos return address; 59 1.1 christos } 60 1.1 christos 61 1.1 christos static SI 62 1.1 christos fr550_check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask) 63 1.1 christos { 64 1.1.1.9 christos if (((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff) 65 1.1 christos || (align_mask > 0x3 66 1.1 christos && ((USI)address >= 0xfeff0000 && (USI)address <= 0xfeffffff))) 67 1.1 christos frv_queue_data_access_error_interrupt (current_cpu, address); 68 1.1 christos 69 1.1 christos return address; 70 1.1 christos } 71 1.1 christos 72 1.1 christos static SI 73 1.1 christos check_data_read_address (SIM_CPU *current_cpu, SI address, int align_mask) 74 1.1 christos { 75 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 76 1.1 christos switch (STATE_ARCHITECTURE (sd)->mach) 77 1.1 christos { 78 1.1 christos case bfd_mach_fr400: 79 1.1 christos case bfd_mach_fr450: 80 1.1 christos address = fr400_check_data_read_address (current_cpu, address, 81 1.1 christos align_mask); 82 1.1 christos break; 83 1.1 christos case bfd_mach_frvtomcat: 84 1.1 christos case bfd_mach_fr500: 85 1.1 christos case bfd_mach_frv: 86 1.1 christos address = fr500_check_data_read_address (current_cpu, address, 87 1.1 christos align_mask); 88 1.1 christos break; 89 1.1 christos case bfd_mach_fr550: 90 1.1 christos address = fr550_check_data_read_address (current_cpu, address, 91 1.1 christos align_mask); 92 1.1 christos break; 93 1.1 christos default: 94 1.1 christos break; 95 1.1 christos } 96 1.1 christos 97 1.1 christos return address; 98 1.1 christos } 99 1.1 christos 100 1.1 christos static SI 101 1.1 christos fr400_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask) 102 1.1 christos { 103 1.1 christos if (address & align_mask) 104 1.1 christos { 105 1.1 christos /* Make sure that this exception is not masked. */ 106 1.1 christos USI isr = GET_ISR (); 107 1.1 christos if (! GET_ISR_EMAM (isr)) 108 1.1 christos { 109 1.1 christos /* Bad alignment causes a data_access_error on fr400. */ 110 1.1 christos frv_queue_data_access_error_interrupt (current_cpu, address); 111 1.1 christos } 112 1.1 christos address &= ~align_mask; 113 1.1 christos } 114 1.1 christos /* Nothing to check. */ 115 1.1 christos return address; 116 1.1 christos } 117 1.1 christos 118 1.1 christos static SI 119 1.1 christos fr500_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask) 120 1.1 christos { 121 1.1.1.9 christos if (((USI)address >= 0xfe000000 && (USI)address <= 0xfe003fff) 122 1.1.1.9 christos || ((USI)address >= 0xfe004000 && (USI)address <= 0xfe3fffff) 123 1.1.1.9 christos || ((USI)address >= 0xfe400000 && (USI)address <= 0xfe403fff) 124 1.1.1.9 christos || ((USI)address >= 0xfe404000 && (USI)address <= 0xfe7fffff)) 125 1.1 christos frv_queue_data_access_exception_interrupt (current_cpu); 126 1.1 christos 127 1.1 christos return address; 128 1.1 christos } 129 1.1 christos 130 1.1 christos static SI 131 1.1 christos fr550_check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask) 132 1.1 christos { 133 1.1 christos /* No alignment restrictions on fr550 */ 134 1.1 christos 135 1.1.1.9 christos if (((USI)address >= 0xfe000000 && (USI)address <= 0xfe3fffff) 136 1.1.1.9 christos || ((USI)address >= 0xfe408000 && (USI)address <= 0xfe7fffff)) 137 1.1 christos frv_queue_data_access_exception_interrupt (current_cpu); 138 1.1 christos else 139 1.1 christos { 140 1.1 christos USI hsr0 = GET_HSR0 (); 141 1.1 christos if (! GET_HSR0_RME (hsr0) 142 1.1.1.9 christos && ((USI)address >= 0xfe400000 && (USI)address <= 0xfe407fff)) 143 1.1 christos frv_queue_data_access_exception_interrupt (current_cpu); 144 1.1 christos } 145 1.1 christos 146 1.1 christos return address; 147 1.1 christos } 148 1.1 christos 149 1.1 christos static SI 150 1.1 christos check_readwrite_address (SIM_CPU *current_cpu, SI address, int align_mask) 151 1.1 christos { 152 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 153 1.1 christos switch (STATE_ARCHITECTURE (sd)->mach) 154 1.1 christos { 155 1.1 christos case bfd_mach_fr400: 156 1.1 christos case bfd_mach_fr450: 157 1.1 christos address = fr400_check_readwrite_address (current_cpu, address, 158 1.1 christos align_mask); 159 1.1 christos break; 160 1.1 christos case bfd_mach_frvtomcat: 161 1.1 christos case bfd_mach_fr500: 162 1.1 christos case bfd_mach_frv: 163 1.1 christos address = fr500_check_readwrite_address (current_cpu, address, 164 1.1 christos align_mask); 165 1.1 christos break; 166 1.1 christos case bfd_mach_fr550: 167 1.1 christos address = fr550_check_readwrite_address (current_cpu, address, 168 1.1 christos align_mask); 169 1.1 christos break; 170 1.1 christos default: 171 1.1 christos break; 172 1.1 christos } 173 1.1 christos 174 1.1 christos return address; 175 1.1 christos } 176 1.1 christos 177 1.1 christos static PCADDR 178 1.1 christos fr400_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address, 179 1.1 christos int align_mask) 180 1.1 christos { 181 1.1 christos if (address & align_mask) 182 1.1 christos { 183 1.1 christos frv_queue_instruction_access_error_interrupt (current_cpu); 184 1.1 christos address &= ~align_mask; 185 1.1 christos } 186 1.1 christos else if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff) 187 1.1 christos frv_queue_instruction_access_error_interrupt (current_cpu); 188 1.1 christos 189 1.1 christos return address; 190 1.1 christos } 191 1.1 christos 192 1.1 christos static PCADDR 193 1.1 christos fr500_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address, 194 1.1 christos int align_mask) 195 1.1 christos { 196 1.1 christos if (address & align_mask) 197 1.1 christos { 198 1.1 christos frv_queue_mem_address_not_aligned_interrupt (current_cpu, address); 199 1.1 christos address &= ~align_mask; 200 1.1 christos } 201 1.1 christos 202 1.1.1.9 christos if (((USI)address >= 0xfeff0600 && (USI)address <= 0xfeff7fff) 203 1.1.1.9 christos || ((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff)) 204 1.1 christos frv_queue_instruction_access_error_interrupt (current_cpu); 205 1.1.1.9 christos else if (((USI)address >= 0xfe004000 && (USI)address <= 0xfe3fffff) 206 1.1.1.9 christos || ((USI)address >= 0xfe400000 && (USI)address <= 0xfe403fff) 207 1.1.1.9 christos || ((USI)address >= 0xfe404000 && (USI)address <= 0xfe7fffff)) 208 1.1 christos frv_queue_instruction_access_exception_interrupt (current_cpu); 209 1.1 christos else 210 1.1 christos { 211 1.1 christos USI hsr0 = GET_HSR0 (); 212 1.1 christos if (! GET_HSR0_RME (hsr0) 213 1.1.1.9 christos && ((USI)address >= 0xfe000000 && (USI)address <= 0xfe003fff)) 214 1.1 christos frv_queue_instruction_access_exception_interrupt (current_cpu); 215 1.1 christos } 216 1.1 christos 217 1.1 christos return address; 218 1.1 christos } 219 1.1 christos 220 1.1 christos static PCADDR 221 1.1 christos fr550_check_insn_read_address (SIM_CPU *current_cpu, PCADDR address, 222 1.1 christos int align_mask) 223 1.1 christos { 224 1.1 christos address &= ~align_mask; 225 1.1 christos 226 1.1 christos if ((USI)address >= 0xfe800000 && (USI)address <= 0xfeffffff) 227 1.1 christos frv_queue_instruction_access_error_interrupt (current_cpu); 228 1.1 christos else if ((USI)address >= 0xfe008000 && (USI)address <= 0xfe7fffff) 229 1.1 christos frv_queue_instruction_access_exception_interrupt (current_cpu); 230 1.1 christos else 231 1.1 christos { 232 1.1 christos USI hsr0 = GET_HSR0 (); 233 1.1 christos if (! GET_HSR0_RME (hsr0) 234 1.1 christos && (USI)address >= 0xfe000000 && (USI)address <= 0xfe007fff) 235 1.1 christos frv_queue_instruction_access_exception_interrupt (current_cpu); 236 1.1 christos } 237 1.1 christos 238 1.1 christos return address; 239 1.1 christos } 240 1.1 christos 241 1.1 christos static PCADDR 242 1.1 christos check_insn_read_address (SIM_CPU *current_cpu, PCADDR address, int align_mask) 243 1.1 christos { 244 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 245 1.1 christos switch (STATE_ARCHITECTURE (sd)->mach) 246 1.1 christos { 247 1.1 christos case bfd_mach_fr400: 248 1.1 christos case bfd_mach_fr450: 249 1.1 christos address = fr400_check_insn_read_address (current_cpu, address, 250 1.1 christos align_mask); 251 1.1 christos break; 252 1.1 christos case bfd_mach_frvtomcat: 253 1.1 christos case bfd_mach_fr500: 254 1.1 christos case bfd_mach_frv: 255 1.1 christos address = fr500_check_insn_read_address (current_cpu, address, 256 1.1 christos align_mask); 257 1.1 christos break; 258 1.1 christos case bfd_mach_fr550: 259 1.1 christos address = fr550_check_insn_read_address (current_cpu, address, 260 1.1 christos align_mask); 261 1.1 christos break; 262 1.1 christos default: 263 1.1 christos break; 264 1.1 christos } 265 1.1 christos 266 1.1 christos return address; 267 1.1 christos } 268 1.1 christos 269 1.1 christos /* Memory reads. */ 270 1.1 christos QI 271 1.1 christos frvbf_read_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address) 272 1.1 christos { 273 1.1 christos USI hsr0 = GET_HSR0 (); 274 1.1 christos FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); 275 1.1 christos 276 1.1 christos /* Check for access exceptions. */ 277 1.1 christos address = check_data_read_address (current_cpu, address, 0); 278 1.1 christos address = check_readwrite_address (current_cpu, address, 0); 279 1.1 christos 280 1.1 christos /* If we need to count cycles, then the cache operation will be 281 1.1 christos initiated from the model profiling functions. 282 1.1 christos See frvbf_model_.... */ 283 1.1 christos if (model_insn) 284 1.1 christos { 285 1.1 christos CPU_LOAD_ADDRESS (current_cpu) = address; 286 1.1 christos CPU_LOAD_LENGTH (current_cpu) = 1; 287 1.1 christos CPU_LOAD_SIGNED (current_cpu) = 1; 288 1.1 christos return 0xb7; /* any random value */ 289 1.1 christos } 290 1.1 christos 291 1.1 christos if (GET_HSR0_DCE (hsr0)) 292 1.1 christos { 293 1.1 christos int cycles; 294 1.1 christos cycles = frv_cache_read (cache, 0, address); 295 1.1 christos if (cycles != 0) 296 1.1 christos return CACHE_RETURN_DATA (cache, 0, address, QI, 1); 297 1.1 christos } 298 1.1 christos 299 1.1 christos return GETMEMQI (current_cpu, pc, address); 300 1.1 christos } 301 1.1 christos 302 1.1 christos UQI 303 1.1 christos frvbf_read_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address) 304 1.1 christos { 305 1.1 christos USI hsr0 = GET_HSR0 (); 306 1.1 christos FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); 307 1.1 christos 308 1.1 christos /* Check for access exceptions. */ 309 1.1 christos address = check_data_read_address (current_cpu, address, 0); 310 1.1 christos address = check_readwrite_address (current_cpu, address, 0); 311 1.1 christos 312 1.1 christos /* If we need to count cycles, then the cache operation will be 313 1.1 christos initiated from the model profiling functions. 314 1.1 christos See frvbf_model_.... */ 315 1.1 christos if (model_insn) 316 1.1 christos { 317 1.1 christos CPU_LOAD_ADDRESS (current_cpu) = address; 318 1.1 christos CPU_LOAD_LENGTH (current_cpu) = 1; 319 1.1 christos CPU_LOAD_SIGNED (current_cpu) = 0; 320 1.1 christos return 0xb7; /* any random value */ 321 1.1 christos } 322 1.1 christos 323 1.1 christos if (GET_HSR0_DCE (hsr0)) 324 1.1 christos { 325 1.1 christos int cycles; 326 1.1 christos cycles = frv_cache_read (cache, 0, address); 327 1.1 christos if (cycles != 0) 328 1.1 christos return CACHE_RETURN_DATA (cache, 0, address, UQI, 1); 329 1.1 christos } 330 1.1 christos 331 1.1 christos return GETMEMUQI (current_cpu, pc, address); 332 1.1 christos } 333 1.1 christos 334 1.1 christos /* Read a HI which spans two cache lines */ 335 1.1 christos static HI 336 1.1 christos read_mem_unaligned_HI (SIM_CPU *current_cpu, IADDR pc, SI address) 337 1.1 christos { 338 1.1 christos HI value = frvbf_read_mem_QI (current_cpu, pc, address); 339 1.1 christos value <<= 8; 340 1.1 christos value |= frvbf_read_mem_UQI (current_cpu, pc, address + 1); 341 1.1 christos return T2H_2 (value); 342 1.1 christos } 343 1.1 christos 344 1.1 christos HI 345 1.1 christos frvbf_read_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address) 346 1.1 christos { 347 1.1 christos USI hsr0; 348 1.1 christos FRV_CACHE *cache; 349 1.1 christos 350 1.1 christos /* Check for access exceptions. */ 351 1.1 christos address = check_data_read_address (current_cpu, address, 1); 352 1.1 christos address = check_readwrite_address (current_cpu, address, 1); 353 1.1 christos 354 1.1 christos /* If we need to count cycles, then the cache operation will be 355 1.1 christos initiated from the model profiling functions. 356 1.1 christos See frvbf_model_.... */ 357 1.1 christos hsr0 = GET_HSR0 (); 358 1.1 christos cache = CPU_DATA_CACHE (current_cpu); 359 1.1 christos if (model_insn) 360 1.1 christos { 361 1.1 christos CPU_LOAD_ADDRESS (current_cpu) = address; 362 1.1 christos CPU_LOAD_LENGTH (current_cpu) = 2; 363 1.1 christos CPU_LOAD_SIGNED (current_cpu) = 1; 364 1.1 christos return 0xb711; /* any random value */ 365 1.1 christos } 366 1.1 christos 367 1.1 christos if (GET_HSR0_DCE (hsr0)) 368 1.1 christos { 369 1.1 christos int cycles; 370 1.1 christos /* Handle access which crosses cache line boundary */ 371 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 372 1.1 christos if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) 373 1.1 christos { 374 1.1 christos if (DATA_CROSSES_CACHE_LINE (cache, address, 2)) 375 1.1 christos return read_mem_unaligned_HI (current_cpu, pc, address); 376 1.1 christos } 377 1.1 christos cycles = frv_cache_read (cache, 0, address); 378 1.1 christos if (cycles != 0) 379 1.1 christos return CACHE_RETURN_DATA (cache, 0, address, HI, 2); 380 1.1 christos } 381 1.1 christos 382 1.1 christos return GETMEMHI (current_cpu, pc, address); 383 1.1 christos } 384 1.1 christos 385 1.1 christos UHI 386 1.1 christos frvbf_read_mem_UHI (SIM_CPU *current_cpu, IADDR pc, SI address) 387 1.1 christos { 388 1.1 christos USI hsr0; 389 1.1 christos FRV_CACHE *cache; 390 1.1 christos 391 1.1 christos /* Check for access exceptions. */ 392 1.1 christos address = check_data_read_address (current_cpu, address, 1); 393 1.1 christos address = check_readwrite_address (current_cpu, address, 1); 394 1.1 christos 395 1.1 christos /* If we need to count cycles, then the cache operation will be 396 1.1 christos initiated from the model profiling functions. 397 1.1 christos See frvbf_model_.... */ 398 1.1 christos hsr0 = GET_HSR0 (); 399 1.1 christos cache = CPU_DATA_CACHE (current_cpu); 400 1.1 christos if (model_insn) 401 1.1 christos { 402 1.1 christos CPU_LOAD_ADDRESS (current_cpu) = address; 403 1.1 christos CPU_LOAD_LENGTH (current_cpu) = 2; 404 1.1 christos CPU_LOAD_SIGNED (current_cpu) = 0; 405 1.1 christos return 0xb711; /* any random value */ 406 1.1 christos } 407 1.1 christos 408 1.1 christos if (GET_HSR0_DCE (hsr0)) 409 1.1 christos { 410 1.1 christos int cycles; 411 1.1 christos /* Handle access which crosses cache line boundary */ 412 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 413 1.1 christos if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) 414 1.1 christos { 415 1.1 christos if (DATA_CROSSES_CACHE_LINE (cache, address, 2)) 416 1.1 christos return read_mem_unaligned_HI (current_cpu, pc, address); 417 1.1 christos } 418 1.1 christos cycles = frv_cache_read (cache, 0, address); 419 1.1 christos if (cycles != 0) 420 1.1 christos return CACHE_RETURN_DATA (cache, 0, address, UHI, 2); 421 1.1 christos } 422 1.1 christos 423 1.1 christos return GETMEMUHI (current_cpu, pc, address); 424 1.1 christos } 425 1.1 christos 426 1.1 christos /* Read a SI which spans two cache lines */ 427 1.1 christos static SI 428 1.1 christos read_mem_unaligned_SI (SIM_CPU *current_cpu, IADDR pc, SI address) 429 1.1 christos { 430 1.1 christos FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); 431 1.1 christos unsigned hi_len = cache->line_size - (address & (cache->line_size - 1)); 432 1.1 christos char valarray[4]; 433 1.1 christos SI SIvalue; 434 1.1 christos HI HIvalue; 435 1.1 christos 436 1.1 christos switch (hi_len) 437 1.1 christos { 438 1.1 christos case 1: 439 1.1 christos valarray[0] = frvbf_read_mem_QI (current_cpu, pc, address); 440 1.1 christos SIvalue = frvbf_read_mem_SI (current_cpu, pc, address + 1); 441 1.1 christos SIvalue = H2T_4 (SIvalue); 442 1.1 christos memcpy (valarray + 1, (char*)&SIvalue, 3); 443 1.1 christos break; 444 1.1 christos case 2: 445 1.1 christos HIvalue = frvbf_read_mem_HI (current_cpu, pc, address); 446 1.1 christos HIvalue = H2T_2 (HIvalue); 447 1.1 christos memcpy (valarray, (char*)&HIvalue, 2); 448 1.1 christos HIvalue = frvbf_read_mem_HI (current_cpu, pc, address + 2); 449 1.1 christos HIvalue = H2T_2 (HIvalue); 450 1.1 christos memcpy (valarray + 2, (char*)&HIvalue, 2); 451 1.1 christos break; 452 1.1 christos case 3: 453 1.1 christos SIvalue = frvbf_read_mem_SI (current_cpu, pc, address - 1); 454 1.1 christos SIvalue = H2T_4 (SIvalue); 455 1.1 christos memcpy (valarray, (char*)&SIvalue, 3); 456 1.1 christos valarray[3] = frvbf_read_mem_QI (current_cpu, pc, address + 3); 457 1.1 christos break; 458 1.1 christos default: 459 1.1 christos abort (); /* can't happen */ 460 1.1 christos } 461 1.1 christos return T2H_4 (*(SI*)valarray); 462 1.1 christos } 463 1.1 christos 464 1.1 christos SI 465 1.1 christos frvbf_read_mem_SI (SIM_CPU *current_cpu, IADDR pc, SI address) 466 1.1 christos { 467 1.1 christos FRV_CACHE *cache; 468 1.1 christos USI hsr0; 469 1.1 christos 470 1.1 christos /* Check for access exceptions. */ 471 1.1 christos address = check_data_read_address (current_cpu, address, 3); 472 1.1 christos address = check_readwrite_address (current_cpu, address, 3); 473 1.1 christos 474 1.1 christos hsr0 = GET_HSR0 (); 475 1.1 christos cache = CPU_DATA_CACHE (current_cpu); 476 1.1 christos /* If we need to count cycles, then the cache operation will be 477 1.1 christos initiated from the model profiling functions. 478 1.1 christos See frvbf_model_.... */ 479 1.1 christos if (model_insn) 480 1.1 christos { 481 1.1 christos CPU_LOAD_ADDRESS (current_cpu) = address; 482 1.1 christos CPU_LOAD_LENGTH (current_cpu) = 4; 483 1.1 christos return 0x37111319; /* any random value */ 484 1.1 christos } 485 1.1 christos 486 1.1 christos if (GET_HSR0_DCE (hsr0)) 487 1.1 christos { 488 1.1 christos int cycles; 489 1.1 christos /* Handle access which crosses cache line boundary */ 490 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 491 1.1 christos if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) 492 1.1 christos { 493 1.1 christos if (DATA_CROSSES_CACHE_LINE (cache, address, 4)) 494 1.1 christos return read_mem_unaligned_SI (current_cpu, pc, address); 495 1.1 christos } 496 1.1 christos cycles = frv_cache_read (cache, 0, address); 497 1.1 christos if (cycles != 0) 498 1.1 christos return CACHE_RETURN_DATA (cache, 0, address, SI, 4); 499 1.1 christos } 500 1.1 christos 501 1.1 christos return GETMEMSI (current_cpu, pc, address); 502 1.1 christos } 503 1.1 christos 504 1.1 christos SI 505 1.1 christos frvbf_read_mem_WI (SIM_CPU *current_cpu, IADDR pc, SI address) 506 1.1 christos { 507 1.1 christos return frvbf_read_mem_SI (current_cpu, pc, address); 508 1.1 christos } 509 1.1 christos 510 1.1 christos /* Read a SI which spans two cache lines */ 511 1.1 christos static DI 512 1.1 christos read_mem_unaligned_DI (SIM_CPU *current_cpu, IADDR pc, SI address) 513 1.1 christos { 514 1.1 christos FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); 515 1.1 christos unsigned hi_len = cache->line_size - (address & (cache->line_size - 1)); 516 1.1 christos DI value, value1; 517 1.1 christos 518 1.1 christos switch (hi_len) 519 1.1 christos { 520 1.1 christos case 1: 521 1.1 christos value = frvbf_read_mem_QI (current_cpu, pc, address); 522 1.1 christos value <<= 56; 523 1.1 christos value1 = frvbf_read_mem_DI (current_cpu, pc, address + 1); 524 1.1 christos value1 = H2T_8 (value1); 525 1.1 christos value |= value1 & ((DI)0x00ffffff << 32); 526 1.1 christos value |= value1 & 0xffffffffu; 527 1.1 christos break; 528 1.1 christos case 2: 529 1.1 christos value = frvbf_read_mem_HI (current_cpu, pc, address); 530 1.1 christos value = H2T_2 (value); 531 1.1 christos value <<= 48; 532 1.1 christos value1 = frvbf_read_mem_DI (current_cpu, pc, address + 2); 533 1.1 christos value1 = H2T_8 (value1); 534 1.1 christos value |= value1 & ((DI)0x0000ffff << 32); 535 1.1 christos value |= value1 & 0xffffffffu; 536 1.1 christos break; 537 1.1 christos case 3: 538 1.1 christos value = frvbf_read_mem_SI (current_cpu, pc, address - 1); 539 1.1 christos value = H2T_4 (value); 540 1.1 christos value <<= 40; 541 1.1 christos value1 = frvbf_read_mem_DI (current_cpu, pc, address + 3); 542 1.1 christos value1 = H2T_8 (value1); 543 1.1 christos value |= value1 & ((DI)0x000000ff << 32); 544 1.1 christos value |= value1 & 0xffffffffu; 545 1.1 christos break; 546 1.1 christos case 4: 547 1.1 christos value = frvbf_read_mem_SI (current_cpu, pc, address); 548 1.1 christos value = H2T_4 (value); 549 1.1 christos value <<= 32; 550 1.1 christos value1 = frvbf_read_mem_SI (current_cpu, pc, address + 4); 551 1.1 christos value1 = H2T_4 (value1); 552 1.1 christos value |= value1 & 0xffffffffu; 553 1.1 christos break; 554 1.1 christos case 5: 555 1.1 christos value = frvbf_read_mem_DI (current_cpu, pc, address - 3); 556 1.1 christos value = H2T_8 (value); 557 1.1 christos value <<= 24; 558 1.1 christos value1 = frvbf_read_mem_SI (current_cpu, pc, address + 5); 559 1.1 christos value1 = H2T_4 (value1); 560 1.1 christos value |= value1 & 0x00ffffff; 561 1.1 christos break; 562 1.1 christos case 6: 563 1.1 christos value = frvbf_read_mem_DI (current_cpu, pc, address - 2); 564 1.1 christos value = H2T_8 (value); 565 1.1 christos value <<= 16; 566 1.1 christos value1 = frvbf_read_mem_HI (current_cpu, pc, address + 6); 567 1.1 christos value1 = H2T_2 (value1); 568 1.1 christos value |= value1 & 0x0000ffff; 569 1.1 christos break; 570 1.1 christos case 7: 571 1.1 christos value = frvbf_read_mem_DI (current_cpu, pc, address - 1); 572 1.1 christos value = H2T_8 (value); 573 1.1 christos value <<= 8; 574 1.1 christos value1 = frvbf_read_mem_QI (current_cpu, pc, address + 7); 575 1.1 christos value |= value1 & 0x000000ff; 576 1.1 christos break; 577 1.1 christos default: 578 1.1 christos abort (); /* can't happen */ 579 1.1 christos } 580 1.1 christos return T2H_8 (value); 581 1.1 christos } 582 1.1 christos 583 1.1 christos DI 584 1.1 christos frvbf_read_mem_DI (SIM_CPU *current_cpu, IADDR pc, SI address) 585 1.1 christos { 586 1.1 christos USI hsr0; 587 1.1 christos FRV_CACHE *cache; 588 1.1 christos 589 1.1 christos /* Check for access exceptions. */ 590 1.1 christos address = check_data_read_address (current_cpu, address, 7); 591 1.1 christos address = check_readwrite_address (current_cpu, address, 7); 592 1.1 christos 593 1.1 christos /* If we need to count cycles, then the cache operation will be 594 1.1 christos initiated from the model profiling functions. 595 1.1 christos See frvbf_model_.... */ 596 1.1 christos hsr0 = GET_HSR0 (); 597 1.1 christos cache = CPU_DATA_CACHE (current_cpu); 598 1.1 christos if (model_insn) 599 1.1 christos { 600 1.1 christos CPU_LOAD_ADDRESS (current_cpu) = address; 601 1.1 christos CPU_LOAD_LENGTH (current_cpu) = 8; 602 1.1 christos return 0x37111319; /* any random value */ 603 1.1 christos } 604 1.1 christos 605 1.1 christos if (GET_HSR0_DCE (hsr0)) 606 1.1 christos { 607 1.1 christos int cycles; 608 1.1 christos /* Handle access which crosses cache line boundary */ 609 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 610 1.1 christos if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) 611 1.1 christos { 612 1.1 christos if (DATA_CROSSES_CACHE_LINE (cache, address, 8)) 613 1.1 christos return read_mem_unaligned_DI (current_cpu, pc, address); 614 1.1 christos } 615 1.1 christos cycles = frv_cache_read (cache, 0, address); 616 1.1 christos if (cycles != 0) 617 1.1 christos return CACHE_RETURN_DATA (cache, 0, address, DI, 8); 618 1.1 christos } 619 1.1 christos 620 1.1 christos return GETMEMDI (current_cpu, pc, address); 621 1.1 christos } 622 1.1 christos 623 1.1 christos DF 624 1.1 christos frvbf_read_mem_DF (SIM_CPU *current_cpu, IADDR pc, SI address) 625 1.1 christos { 626 1.1 christos USI hsr0; 627 1.1 christos FRV_CACHE *cache; 628 1.1 christos 629 1.1 christos /* Check for access exceptions. */ 630 1.1 christos address = check_data_read_address (current_cpu, address, 7); 631 1.1 christos address = check_readwrite_address (current_cpu, address, 7); 632 1.1 christos 633 1.1 christos /* If we need to count cycles, then the cache operation will be 634 1.1 christos initiated from the model profiling functions. 635 1.1 christos See frvbf_model_.... */ 636 1.1 christos hsr0 = GET_HSR0 (); 637 1.1 christos cache = CPU_DATA_CACHE (current_cpu); 638 1.1 christos if (model_insn) 639 1.1 christos { 640 1.1 christos CPU_LOAD_ADDRESS (current_cpu) = address; 641 1.1 christos CPU_LOAD_LENGTH (current_cpu) = 8; 642 1.1 christos return 0x37111319; /* any random value */ 643 1.1 christos } 644 1.1 christos 645 1.1 christos if (GET_HSR0_DCE (hsr0)) 646 1.1 christos { 647 1.1 christos int cycles; 648 1.1 christos /* Handle access which crosses cache line boundary */ 649 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 650 1.1 christos if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) 651 1.1 christos { 652 1.1 christos if (DATA_CROSSES_CACHE_LINE (cache, address, 8)) 653 1.1 christos return read_mem_unaligned_DI (current_cpu, pc, address); 654 1.1 christos } 655 1.1 christos cycles = frv_cache_read (cache, 0, address); 656 1.1 christos if (cycles != 0) 657 1.1 christos return CACHE_RETURN_DATA (cache, 0, address, DF, 8); 658 1.1 christos } 659 1.1 christos 660 1.1 christos return GETMEMDF (current_cpu, pc, address); 661 1.1 christos } 662 1.1 christos 663 1.1 christos USI 664 1.1 christos frvbf_read_imem_USI (SIM_CPU *current_cpu, PCADDR vpc) 665 1.1 christos { 666 1.1 christos USI hsr0; 667 1.1 christos vpc = check_insn_read_address (current_cpu, vpc, 3); 668 1.1 christos 669 1.1 christos hsr0 = GET_HSR0 (); 670 1.1 christos if (GET_HSR0_ICE (hsr0)) 671 1.1 christos { 672 1.1 christos FRV_CACHE *cache; 673 1.1.1.10 christos SI value; 674 1.1 christos 675 1.1 christos /* We don't want this to show up in the cache statistics. That read 676 1.1 christos is done in frvbf_simulate_insn_prefetch. So read the cache or memory 677 1.1 christos passively here. */ 678 1.1 christos cache = CPU_INSN_CACHE (current_cpu); 679 1.1 christos if (frv_cache_read_passive_SI (cache, vpc, &value)) 680 1.1 christos return value; 681 1.1 christos } 682 1.1 christos return sim_core_read_unaligned_4 (current_cpu, vpc, read_map, vpc); 683 1.1 christos } 684 1.1 christos 685 1.1 christos static SI 686 1.1 christos fr400_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask) 687 1.1 christos { 688 1.1 christos if (align_mask == 7 689 1.1 christos && address >= 0xfe800000 && address <= 0xfeffffff) 690 1.1 christos frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR); 691 1.1 christos 692 1.1 christos return address; 693 1.1 christos } 694 1.1 christos 695 1.1 christos static SI 696 1.1 christos fr500_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask) 697 1.1 christos { 698 1.1 christos if (address & align_mask) 699 1.1 christos { 700 1.1 christos struct frv_interrupt_queue_element *item = 701 1.1 christos frv_queue_mem_address_not_aligned_interrupt (current_cpu, address); 702 1.1 christos /* Record the correct vliw slot with the interrupt. */ 703 1.1 christos if (item != NULL) 704 1.1 christos item->slot = frv_interrupt_state.slot; 705 1.1 christos address &= ~align_mask; 706 1.1 christos } 707 1.1.1.9 christos if ((address >= 0xfeff0600 && address <= 0xfeff7fff) 708 1.1.1.9 christos || (address >= 0xfe800000 && address <= 0xfefeffff)) 709 1.1 christos frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR); 710 1.1 christos 711 1.1 christos return address; 712 1.1 christos } 713 1.1 christos 714 1.1 christos static SI 715 1.1 christos fr550_check_write_address (SIM_CPU *current_cpu, SI address, int align_mask) 716 1.1 christos { 717 1.1.1.9 christos if (((USI)address >= 0xfe800000 && (USI)address <= 0xfefeffff) 718 1.1 christos || (align_mask > 0x3 719 1.1 christos && ((USI)address >= 0xfeff0000 && (USI)address <= 0xfeffffff))) 720 1.1 christos frv_queue_program_interrupt (current_cpu, FRV_DATA_STORE_ERROR); 721 1.1 christos 722 1.1 christos return address; 723 1.1 christos } 724 1.1 christos 725 1.1 christos static SI 726 1.1 christos check_write_address (SIM_CPU *current_cpu, SI address, int align_mask) 727 1.1 christos { 728 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 729 1.1 christos switch (STATE_ARCHITECTURE (sd)->mach) 730 1.1 christos { 731 1.1 christos case bfd_mach_fr400: 732 1.1 christos case bfd_mach_fr450: 733 1.1 christos address = fr400_check_write_address (current_cpu, address, align_mask); 734 1.1 christos break; 735 1.1 christos case bfd_mach_frvtomcat: 736 1.1 christos case bfd_mach_fr500: 737 1.1 christos case bfd_mach_frv: 738 1.1 christos address = fr500_check_write_address (current_cpu, address, align_mask); 739 1.1 christos break; 740 1.1 christos case bfd_mach_fr550: 741 1.1 christos address = fr550_check_write_address (current_cpu, address, align_mask); 742 1.1 christos break; 743 1.1 christos default: 744 1.1 christos break; 745 1.1 christos } 746 1.1 christos return address; 747 1.1 christos } 748 1.1 christos 749 1.1 christos void 750 1.1 christos frvbf_write_mem_QI (SIM_CPU *current_cpu, IADDR pc, SI address, QI value) 751 1.1 christos { 752 1.1 christos USI hsr0; 753 1.1 christos hsr0 = GET_HSR0 (); 754 1.1 christos if (GET_HSR0_DCE (hsr0)) 755 1.1 christos sim_queue_fn_mem_qi_write (current_cpu, frvbf_mem_set_QI, address, value); 756 1.1 christos else 757 1.1 christos sim_queue_mem_qi_write (current_cpu, address, value); 758 1.1 christos frv_set_write_queue_slot (current_cpu); 759 1.1 christos } 760 1.1 christos 761 1.1 christos void 762 1.1 christos frvbf_write_mem_UQI (SIM_CPU *current_cpu, IADDR pc, SI address, UQI value) 763 1.1 christos { 764 1.1 christos frvbf_write_mem_QI (current_cpu, pc, address, value); 765 1.1 christos } 766 1.1 christos 767 1.1 christos void 768 1.1 christos frvbf_write_mem_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value) 769 1.1 christos { 770 1.1 christos USI hsr0; 771 1.1 christos hsr0 = GET_HSR0 (); 772 1.1 christos if (GET_HSR0_DCE (hsr0)) 773 1.1 christos sim_queue_fn_mem_hi_write (current_cpu, frvbf_mem_set_HI, address, value); 774 1.1 christos else 775 1.1 christos sim_queue_mem_hi_write (current_cpu, address, value); 776 1.1 christos frv_set_write_queue_slot (current_cpu); 777 1.1 christos } 778 1.1 christos 779 1.1 christos void 780 1.1 christos frvbf_write_mem_UHI (SIM_CPU *current_cpu, IADDR pc, SI address, UHI value) 781 1.1 christos { 782 1.1 christos frvbf_write_mem_HI (current_cpu, pc, address, value); 783 1.1 christos } 784 1.1 christos 785 1.1 christos void 786 1.1 christos frvbf_write_mem_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value) 787 1.1 christos { 788 1.1 christos USI hsr0; 789 1.1 christos hsr0 = GET_HSR0 (); 790 1.1 christos if (GET_HSR0_DCE (hsr0)) 791 1.1 christos sim_queue_fn_mem_si_write (current_cpu, frvbf_mem_set_SI, address, value); 792 1.1 christos else 793 1.1 christos sim_queue_mem_si_write (current_cpu, address, value); 794 1.1 christos frv_set_write_queue_slot (current_cpu); 795 1.1 christos } 796 1.1 christos 797 1.1 christos void 798 1.1 christos frvbf_write_mem_WI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value) 799 1.1 christos { 800 1.1 christos frvbf_write_mem_SI (current_cpu, pc, address, value); 801 1.1 christos } 802 1.1 christos 803 1.1 christos void 804 1.1 christos frvbf_write_mem_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value) 805 1.1 christos { 806 1.1 christos USI hsr0; 807 1.1 christos hsr0 = GET_HSR0 (); 808 1.1 christos if (GET_HSR0_DCE (hsr0)) 809 1.1 christos sim_queue_fn_mem_di_write (current_cpu, frvbf_mem_set_DI, address, value); 810 1.1 christos else 811 1.1 christos sim_queue_mem_di_write (current_cpu, address, value); 812 1.1 christos frv_set_write_queue_slot (current_cpu); 813 1.1 christos } 814 1.1 christos 815 1.1 christos void 816 1.1 christos frvbf_write_mem_DF (SIM_CPU *current_cpu, IADDR pc, SI address, DF value) 817 1.1 christos { 818 1.1 christos USI hsr0; 819 1.1 christos hsr0 = GET_HSR0 (); 820 1.1 christos if (GET_HSR0_DCE (hsr0)) 821 1.1 christos sim_queue_fn_mem_df_write (current_cpu, frvbf_mem_set_DF, address, value); 822 1.1 christos else 823 1.1 christos sim_queue_mem_df_write (current_cpu, address, value); 824 1.1 christos frv_set_write_queue_slot (current_cpu); 825 1.1 christos } 826 1.1 christos 827 1.1 christos /* Memory writes. These do the actual writing through the cache. */ 828 1.1 christos void 829 1.1 christos frvbf_mem_set_QI (SIM_CPU *current_cpu, IADDR pc, SI address, QI value) 830 1.1 christos { 831 1.1 christos FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); 832 1.1 christos 833 1.1 christos /* Check for access errors. */ 834 1.1 christos address = check_write_address (current_cpu, address, 0); 835 1.1 christos address = check_readwrite_address (current_cpu, address, 0); 836 1.1 christos 837 1.1 christos /* If we need to count cycles, then submit the write request to the cache 838 1.1 christos and let it prioritize the request. Otherwise perform the write now. */ 839 1.1 christos if (model_insn) 840 1.1 christos { 841 1.1 christos int slot = UNIT_I0; 842 1.1 christos frv_cache_request_store (cache, address, slot, (char *)&value, 843 1.1 christos sizeof (value)); 844 1.1 christos } 845 1.1 christos else 846 1.1 christos frv_cache_write (cache, address, (char *)&value, sizeof (value)); 847 1.1 christos } 848 1.1 christos 849 1.1 christos /* Write a HI which spans two cache lines */ 850 1.1 christos static void 851 1.1 christos mem_set_unaligned_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value) 852 1.1 christos { 853 1.1 christos FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); 854 1.1 christos /* value is already in target byte order */ 855 1.1 christos frv_cache_write (cache, address, (char *)&value, 1); 856 1.1 christos frv_cache_write (cache, address + 1, ((char *)&value + 1), 1); 857 1.1 christos } 858 1.1 christos 859 1.1 christos void 860 1.1 christos frvbf_mem_set_HI (SIM_CPU *current_cpu, IADDR pc, SI address, HI value) 861 1.1 christos { 862 1.1 christos FRV_CACHE *cache; 863 1.1 christos 864 1.1 christos /* Check for access errors. */ 865 1.1 christos address = check_write_address (current_cpu, address, 1); 866 1.1 christos address = check_readwrite_address (current_cpu, address, 1); 867 1.1 christos 868 1.1 christos /* If we need to count cycles, then submit the write request to the cache 869 1.1 christos and let it prioritize the request. Otherwise perform the write now. */ 870 1.1 christos value = H2T_2 (value); 871 1.1 christos cache = CPU_DATA_CACHE (current_cpu); 872 1.1 christos if (model_insn) 873 1.1 christos { 874 1.1 christos int slot = UNIT_I0; 875 1.1 christos frv_cache_request_store (cache, address, slot, 876 1.1 christos (char *)&value, sizeof (value)); 877 1.1 christos } 878 1.1 christos else 879 1.1 christos { 880 1.1 christos /* Handle access which crosses cache line boundary */ 881 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 882 1.1 christos if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) 883 1.1 christos { 884 1.1 christos if (DATA_CROSSES_CACHE_LINE (cache, address, 2)) 885 1.1 christos { 886 1.1 christos mem_set_unaligned_HI (current_cpu, pc, address, value); 887 1.1 christos return; 888 1.1 christos } 889 1.1 christos } 890 1.1 christos frv_cache_write (cache, address, (char *)&value, sizeof (value)); 891 1.1 christos } 892 1.1 christos } 893 1.1 christos 894 1.1 christos /* Write a SI which spans two cache lines */ 895 1.1 christos static void 896 1.1 christos mem_set_unaligned_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value) 897 1.1 christos { 898 1.1 christos FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); 899 1.1 christos unsigned hi_len = cache->line_size - (address & (cache->line_size - 1)); 900 1.1 christos /* value is already in target byte order */ 901 1.1 christos frv_cache_write (cache, address, (char *)&value, hi_len); 902 1.1 christos frv_cache_write (cache, address + hi_len, (char *)&value + hi_len, 4 - hi_len); 903 1.1 christos } 904 1.1 christos 905 1.1 christos void 906 1.1 christos frvbf_mem_set_SI (SIM_CPU *current_cpu, IADDR pc, SI address, SI value) 907 1.1 christos { 908 1.1 christos FRV_CACHE *cache; 909 1.1 christos 910 1.1 christos /* Check for access errors. */ 911 1.1 christos address = check_write_address (current_cpu, address, 3); 912 1.1 christos address = check_readwrite_address (current_cpu, address, 3); 913 1.1 christos 914 1.1 christos /* If we need to count cycles, then submit the write request to the cache 915 1.1 christos and let it prioritize the request. Otherwise perform the write now. */ 916 1.1 christos cache = CPU_DATA_CACHE (current_cpu); 917 1.1 christos value = H2T_4 (value); 918 1.1 christos if (model_insn) 919 1.1 christos { 920 1.1 christos int slot = UNIT_I0; 921 1.1 christos frv_cache_request_store (cache, address, slot, 922 1.1 christos (char *)&value, sizeof (value)); 923 1.1 christos } 924 1.1 christos else 925 1.1 christos { 926 1.1 christos /* Handle access which crosses cache line boundary */ 927 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 928 1.1 christos if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) 929 1.1 christos { 930 1.1 christos if (DATA_CROSSES_CACHE_LINE (cache, address, 4)) 931 1.1 christos { 932 1.1 christos mem_set_unaligned_SI (current_cpu, pc, address, value); 933 1.1 christos return; 934 1.1 christos } 935 1.1 christos } 936 1.1 christos frv_cache_write (cache, address, (char *)&value, sizeof (value)); 937 1.1 christos } 938 1.1 christos } 939 1.1 christos 940 1.1 christos /* Write a DI which spans two cache lines */ 941 1.1 christos static void 942 1.1 christos mem_set_unaligned_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value) 943 1.1 christos { 944 1.1 christos FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); 945 1.1 christos unsigned hi_len = cache->line_size - (address & (cache->line_size - 1)); 946 1.1 christos /* value is already in target byte order */ 947 1.1 christos frv_cache_write (cache, address, (char *)&value, hi_len); 948 1.1 christos frv_cache_write (cache, address + hi_len, (char *)&value + hi_len, 8 - hi_len); 949 1.1 christos } 950 1.1 christos 951 1.1 christos void 952 1.1 christos frvbf_mem_set_DI (SIM_CPU *current_cpu, IADDR pc, SI address, DI value) 953 1.1 christos { 954 1.1 christos FRV_CACHE *cache; 955 1.1 christos 956 1.1 christos /* Check for access errors. */ 957 1.1 christos address = check_write_address (current_cpu, address, 7); 958 1.1 christos address = check_readwrite_address (current_cpu, address, 7); 959 1.1 christos 960 1.1 christos /* If we need to count cycles, then submit the write request to the cache 961 1.1 christos and let it prioritize the request. Otherwise perform the write now. */ 962 1.1 christos value = H2T_8 (value); 963 1.1 christos cache = CPU_DATA_CACHE (current_cpu); 964 1.1 christos if (model_insn) 965 1.1 christos { 966 1.1 christos int slot = UNIT_I0; 967 1.1 christos frv_cache_request_store (cache, address, slot, 968 1.1 christos (char *)&value, sizeof (value)); 969 1.1 christos } 970 1.1 christos else 971 1.1 christos { 972 1.1 christos /* Handle access which crosses cache line boundary */ 973 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 974 1.1 christos if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) 975 1.1 christos { 976 1.1 christos if (DATA_CROSSES_CACHE_LINE (cache, address, 8)) 977 1.1 christos { 978 1.1 christos mem_set_unaligned_DI (current_cpu, pc, address, value); 979 1.1 christos return; 980 1.1 christos } 981 1.1 christos } 982 1.1 christos frv_cache_write (cache, address, (char *)&value, sizeof (value)); 983 1.1 christos } 984 1.1 christos } 985 1.1 christos 986 1.1 christos void 987 1.1 christos frvbf_mem_set_DF (SIM_CPU *current_cpu, IADDR pc, SI address, DF value) 988 1.1 christos { 989 1.1 christos FRV_CACHE *cache; 990 1.1 christos 991 1.1 christos /* Check for access errors. */ 992 1.1 christos address = check_write_address (current_cpu, address, 7); 993 1.1 christos address = check_readwrite_address (current_cpu, address, 7); 994 1.1 christos 995 1.1 christos /* If we need to count cycles, then submit the write request to the cache 996 1.1 christos and let it prioritize the request. Otherwise perform the write now. */ 997 1.1 christos value = H2T_8 (value); 998 1.1 christos cache = CPU_DATA_CACHE (current_cpu); 999 1.1 christos if (model_insn) 1000 1.1 christos { 1001 1.1 christos int slot = UNIT_I0; 1002 1.1 christos frv_cache_request_store (cache, address, slot, 1003 1.1 christos (char *)&value, sizeof (value)); 1004 1.1 christos } 1005 1.1 christos else 1006 1.1 christos { 1007 1.1 christos /* Handle access which crosses cache line boundary */ 1008 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 1009 1.1 christos if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) 1010 1.1 christos { 1011 1.1 christos if (DATA_CROSSES_CACHE_LINE (cache, address, 8)) 1012 1.1 christos { 1013 1.1 christos mem_set_unaligned_DI (current_cpu, pc, address, value); 1014 1.1 christos return; 1015 1.1 christos } 1016 1.1 christos } 1017 1.1 christos frv_cache_write (cache, address, (char *)&value, sizeof (value)); 1018 1.1 christos } 1019 1.1 christos } 1020 1.1 christos 1021 1.1 christos void 1022 1.1 christos frvbf_mem_set_XI (SIM_CPU *current_cpu, IADDR pc, SI address, SI *value) 1023 1.1 christos { 1024 1.1 christos int i; 1025 1.1 christos FRV_CACHE *cache; 1026 1.1 christos 1027 1.1 christos /* Check for access errors. */ 1028 1.1 christos address = check_write_address (current_cpu, address, 0xf); 1029 1.1 christos address = check_readwrite_address (current_cpu, address, 0xf); 1030 1.1 christos 1031 1.1 christos /* TODO -- reverse word order as well? */ 1032 1.1 christos for (i = 0; i < 4; ++i) 1033 1.1 christos value[i] = H2T_4 (value[i]); 1034 1.1 christos 1035 1.1 christos /* If we need to count cycles, then submit the write request to the cache 1036 1.1 christos and let it prioritize the request. Otherwise perform the write now. */ 1037 1.1 christos cache = CPU_DATA_CACHE (current_cpu); 1038 1.1 christos if (model_insn) 1039 1.1 christos { 1040 1.1 christos int slot = UNIT_I0; 1041 1.1 christos frv_cache_request_store (cache, address, slot, (char*)value, 16); 1042 1.1 christos } 1043 1.1 christos else 1044 1.1 christos frv_cache_write (cache, address, (char*)value, 16); 1045 1.1 christos } 1046 1.1 christos 1047 1.1 christos /* Record the current VLIW slot on the element at the top of the write queue. 1048 1.1 christos */ 1049 1.1 christos void 1050 1.1 christos frv_set_write_queue_slot (SIM_CPU *current_cpu) 1051 1.1 christos { 1052 1.1 christos FRV_VLIW *vliw = CPU_VLIW (current_cpu); 1053 1.1 christos int slot = vliw->next_slot - 1; 1054 1.1 christos CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (current_cpu); 1055 1.1 christos int ix = CGEN_WRITE_QUEUE_INDEX (q) - 1; 1056 1.1 christos CGEN_WRITE_QUEUE_ELEMENT *item = CGEN_WRITE_QUEUE_ELEMENT (q, ix); 1057 1.1 christos CGEN_WRITE_QUEUE_ELEMENT_PIPE (item) = (*vliw->current_vliw)[slot]; 1058 1.1 christos } 1059