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