1 /* frv simulator support code 2 Copyright (C) 1998-2024 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 /* This must come before any other includes. */ 21 #include "defs.h" 22 23 #define WANT_CPU 24 #define WANT_CPU_FRVBF 25 26 #include "sim-main.h" 27 #include "cgen-mem.h" 28 #include "cgen-ops.h" 29 #include "cgen-engine.h" 30 #include "cgen-par.h" 31 #include "bfd.h" 32 #include "sim/sim-frv.h" 33 #include <math.h> 34 #include <stdlib.h> 35 36 /* Maintain a flag in order to know when to write the address of the next 37 VLIW instruction into the LR register. Used by JMPL. JMPIL, and CALL 38 insns. */ 39 int frvbf_write_next_vliw_addr_to_LR; 40 41 /* The contents of BUF are in target byte order. */ 42 int 43 frvbf_fetch_register (SIM_CPU *current_cpu, int rn, void *buf, int len) 44 { 45 if (SIM_FRV_GR0_REGNUM <= rn && rn <= SIM_FRV_GR63_REGNUM) 46 { 47 int hi_available, lo_available; 48 int grn = rn - SIM_FRV_GR0_REGNUM; 49 50 frv_gr_registers_available (current_cpu, &hi_available, &lo_available); 51 52 if ((grn < 32 && !lo_available) || (grn >= 32 && !hi_available)) 53 return 0; 54 else 55 SETTSI (buf, GET_H_GR (grn)); 56 } 57 else if (SIM_FRV_FR0_REGNUM <= rn && rn <= SIM_FRV_FR63_REGNUM) 58 { 59 int hi_available, lo_available; 60 int frn = rn - SIM_FRV_FR0_REGNUM; 61 62 frv_fr_registers_available (current_cpu, &hi_available, &lo_available); 63 64 if ((frn < 32 && !lo_available) || (frn >= 32 && !hi_available)) 65 return 0; 66 else 67 SETTSI (buf, GET_H_FR (frn)); 68 } 69 else if (rn == SIM_FRV_PC_REGNUM) 70 SETTSI (buf, GET_H_PC ()); 71 else if (SIM_FRV_SPR0_REGNUM <= rn && rn <= SIM_FRV_SPR4095_REGNUM) 72 { 73 /* Make sure the register is implemented. */ 74 FRV_REGISTER_CONTROL *control = CPU_REGISTER_CONTROL (current_cpu); 75 int spr = rn - SIM_FRV_SPR0_REGNUM; 76 if (! control->spr[spr].implemented) 77 return 0; 78 SETTSI (buf, GET_H_SPR (spr)); 79 } 80 else 81 { 82 SETTSI (buf, 0xdeadbeef); 83 return 0; 84 } 85 86 return len; 87 } 88 89 /* The contents of BUF are in target byte order. */ 90 91 int 92 frvbf_store_register (SIM_CPU *current_cpu, int rn, const void *buf, int len) 93 { 94 if (SIM_FRV_GR0_REGNUM <= rn && rn <= SIM_FRV_GR63_REGNUM) 95 { 96 int hi_available, lo_available; 97 int grn = rn - SIM_FRV_GR0_REGNUM; 98 99 frv_gr_registers_available (current_cpu, &hi_available, &lo_available); 100 101 if ((grn < 32 && !lo_available) || (grn >= 32 && !hi_available)) 102 return 0; 103 else 104 SET_H_GR (grn, GETTSI (buf)); 105 } 106 else if (SIM_FRV_FR0_REGNUM <= rn && rn <= SIM_FRV_FR63_REGNUM) 107 { 108 int hi_available, lo_available; 109 int frn = rn - SIM_FRV_FR0_REGNUM; 110 111 frv_fr_registers_available (current_cpu, &hi_available, &lo_available); 112 113 if ((frn < 32 && !lo_available) || (frn >= 32 && !hi_available)) 114 return 0; 115 else 116 SET_H_FR (frn, GETTSI (buf)); 117 } 118 else if (rn == SIM_FRV_PC_REGNUM) 119 SET_H_PC (GETTSI (buf)); 120 else if (SIM_FRV_SPR0_REGNUM <= rn && rn <= SIM_FRV_SPR4095_REGNUM) 121 { 122 /* Make sure the register is implemented. */ 123 FRV_REGISTER_CONTROL *control = CPU_REGISTER_CONTROL (current_cpu); 124 int spr = rn - SIM_FRV_SPR0_REGNUM; 125 if (! control->spr[spr].implemented) 126 return 0; 127 SET_H_SPR (spr, GETTSI (buf)); 128 } 129 else 130 return 0; 131 132 return len; 133 } 134 135 /* Cover fns to access the general registers. */ 136 USI 137 frvbf_h_gr_get_handler (SIM_CPU *current_cpu, UINT gr) 138 { 139 frv_check_gr_access (current_cpu, gr); 140 return CPU (h_gr[gr]); 141 } 142 143 void 144 frvbf_h_gr_set_handler (SIM_CPU *current_cpu, UINT gr, USI newval) 145 { 146 frv_check_gr_access (current_cpu, gr); 147 148 if (gr == 0) 149 return; /* Storing into gr0 has no effect. */ 150 151 CPU (h_gr[gr]) = newval; 152 } 153 154 /* Cover fns to access the floating point registers. */ 155 SF 156 frvbf_h_fr_get_handler (SIM_CPU *current_cpu, UINT fr) 157 { 158 frv_check_fr_access (current_cpu, fr); 159 return CPU (h_fr[fr]); 160 } 161 162 void 163 frvbf_h_fr_set_handler (SIM_CPU *current_cpu, UINT fr, SF newval) 164 { 165 frv_check_fr_access (current_cpu, fr); 166 CPU (h_fr[fr]) = newval; 167 } 168 169 /* Cover fns to access the general registers as double words. */ 170 static UINT 171 check_register_alignment (SIM_CPU *current_cpu, UINT reg, int align_mask) 172 { 173 if (reg & align_mask) 174 { 175 SIM_DESC sd = CPU_STATE (current_cpu); 176 switch (STATE_ARCHITECTURE (sd)->mach) 177 { 178 /* Note: there is a discrepancy between V2.2 of the FR400 179 instruction manual and the various FR4xx LSI specs. 180 The former claims that unaligned registers cause a 181 register_exception while the latter say it's an 182 illegal_instruction. The LSI specs appear to be 183 correct; in fact, the FR4xx series is not documented 184 as having a register_exception. */ 185 case bfd_mach_fr400: 186 case bfd_mach_fr450: 187 case bfd_mach_fr550: 188 frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION); 189 break; 190 case bfd_mach_frvtomcat: 191 case bfd_mach_fr500: 192 case bfd_mach_frv: 193 frv_queue_register_exception_interrupt (current_cpu, 194 FRV_REC_UNALIGNED); 195 break; 196 default: 197 break; 198 } 199 200 reg &= ~align_mask; 201 } 202 203 return reg; 204 } 205 206 static UINT 207 check_fr_register_alignment (SIM_CPU *current_cpu, UINT reg, int align_mask) 208 { 209 if (reg & align_mask) 210 { 211 SIM_DESC sd = CPU_STATE (current_cpu); 212 switch (STATE_ARCHITECTURE (sd)->mach) 213 { 214 /* See comment in check_register_alignment(). */ 215 case bfd_mach_fr400: 216 case bfd_mach_fr450: 217 case bfd_mach_fr550: 218 frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION); 219 break; 220 case bfd_mach_frvtomcat: 221 case bfd_mach_fr500: 222 case bfd_mach_frv: 223 { 224 struct frv_fp_exception_info fp_info = { 225 FSR_NO_EXCEPTION, FTT_INVALID_FR 226 }; 227 frv_queue_fp_exception_interrupt (current_cpu, & fp_info); 228 } 229 break; 230 default: 231 break; 232 } 233 234 reg &= ~align_mask; 235 } 236 237 return reg; 238 } 239 240 static UINT 241 check_memory_alignment (SIM_CPU *current_cpu, SI address, int align_mask) 242 { 243 if (address & align_mask) 244 { 245 SIM_DESC sd = CPU_STATE (current_cpu); 246 switch (STATE_ARCHITECTURE (sd)->mach) 247 { 248 /* See comment in check_register_alignment(). */ 249 case bfd_mach_fr400: 250 case bfd_mach_fr450: 251 frv_queue_data_access_error_interrupt (current_cpu, address); 252 break; 253 case bfd_mach_frvtomcat: 254 case bfd_mach_fr500: 255 case bfd_mach_frv: 256 frv_queue_mem_address_not_aligned_interrupt (current_cpu, address); 257 break; 258 default: 259 break; 260 } 261 262 address &= ~align_mask; 263 } 264 265 return address; 266 } 267 268 DI 269 frvbf_h_gr_double_get_handler (SIM_CPU *current_cpu, UINT gr) 270 { 271 DI value; 272 273 if (gr == 0) 274 return 0; /* gr0 is always 0. */ 275 276 /* Check the register alignment. */ 277 gr = check_register_alignment (current_cpu, gr, 1); 278 279 value = GET_H_GR (gr); 280 value <<= 32; 281 value |= (USI) GET_H_GR (gr + 1); 282 return value; 283 } 284 285 void 286 frvbf_h_gr_double_set_handler (SIM_CPU *current_cpu, UINT gr, DI newval) 287 { 288 if (gr == 0) 289 return; /* Storing into gr0 has no effect. */ 290 291 /* Check the register alignment. */ 292 gr = check_register_alignment (current_cpu, gr, 1); 293 294 SET_H_GR (gr , (newval >> 32) & 0xffffffff); 295 SET_H_GR (gr + 1, (newval ) & 0xffffffff); 296 } 297 298 /* Cover fns to access the floating point register as double words. */ 299 DF 300 frvbf_h_fr_double_get_handler (SIM_CPU *current_cpu, UINT fr) 301 { 302 union { 303 SF as_sf[2]; 304 DF as_df; 305 } value; 306 307 /* Check the register alignment. */ 308 fr = check_fr_register_alignment (current_cpu, fr, 1); 309 310 if (HOST_BYTE_ORDER == BFD_ENDIAN_LITTLE) 311 { 312 value.as_sf[1] = GET_H_FR (fr); 313 value.as_sf[0] = GET_H_FR (fr + 1); 314 } 315 else 316 { 317 value.as_sf[0] = GET_H_FR (fr); 318 value.as_sf[1] = GET_H_FR (fr + 1); 319 } 320 321 return value.as_df; 322 } 323 324 void 325 frvbf_h_fr_double_set_handler (SIM_CPU *current_cpu, UINT fr, DF newval) 326 { 327 union { 328 SF as_sf[2]; 329 DF as_df; 330 } value; 331 332 /* Check the register alignment. */ 333 fr = check_fr_register_alignment (current_cpu, fr, 1); 334 335 value.as_df = newval; 336 if (HOST_BYTE_ORDER == BFD_ENDIAN_LITTLE) 337 { 338 SET_H_FR (fr , value.as_sf[1]); 339 SET_H_FR (fr + 1, value.as_sf[0]); 340 } 341 else 342 { 343 SET_H_FR (fr , value.as_sf[0]); 344 SET_H_FR (fr + 1, value.as_sf[1]); 345 } 346 } 347 348 /* Cover fns to access the floating point register as integer words. */ 349 USI 350 frvbf_h_fr_int_get_handler (SIM_CPU *current_cpu, UINT fr) 351 { 352 union { 353 SF as_sf; 354 USI as_usi; 355 } value; 356 357 value.as_sf = GET_H_FR (fr); 358 return value.as_usi; 359 } 360 361 void 362 frvbf_h_fr_int_set_handler (SIM_CPU *current_cpu, UINT fr, USI newval) 363 { 364 union { 365 SF as_sf; 366 USI as_usi; 367 } value; 368 369 value.as_usi = newval; 370 SET_H_FR (fr, value.as_sf); 371 } 372 373 /* Cover fns to access the coprocessor registers as double words. */ 374 DI 375 frvbf_h_cpr_double_get_handler (SIM_CPU *current_cpu, UINT cpr) 376 { 377 DI value; 378 379 /* Check the register alignment. */ 380 cpr = check_register_alignment (current_cpu, cpr, 1); 381 382 value = GET_H_CPR (cpr); 383 value <<= 32; 384 value |= (USI) GET_H_CPR (cpr + 1); 385 return value; 386 } 387 388 void 389 frvbf_h_cpr_double_set_handler (SIM_CPU *current_cpu, UINT cpr, DI newval) 390 { 391 /* Check the register alignment. */ 392 cpr = check_register_alignment (current_cpu, cpr, 1); 393 394 SET_H_CPR (cpr , (newval >> 32) & 0xffffffff); 395 SET_H_CPR (cpr + 1, (newval ) & 0xffffffff); 396 } 397 398 /* Cover fns to write registers as quad words. */ 399 void 400 frvbf_h_gr_quad_set_handler (SIM_CPU *current_cpu, UINT gr, SI *newval) 401 { 402 if (gr == 0) 403 return; /* Storing into gr0 has no effect. */ 404 405 /* Check the register alignment. */ 406 gr = check_register_alignment (current_cpu, gr, 3); 407 408 SET_H_GR (gr , newval[0]); 409 SET_H_GR (gr + 1, newval[1]); 410 SET_H_GR (gr + 2, newval[2]); 411 SET_H_GR (gr + 3, newval[3]); 412 } 413 414 void 415 frvbf_h_fr_quad_set_handler (SIM_CPU *current_cpu, UINT fr, SI *newval) 416 { 417 /* Check the register alignment. */ 418 fr = check_fr_register_alignment (current_cpu, fr, 3); 419 420 SET_H_FR (fr , newval[0]); 421 SET_H_FR (fr + 1, newval[1]); 422 SET_H_FR (fr + 2, newval[2]); 423 SET_H_FR (fr + 3, newval[3]); 424 } 425 426 void 427 frvbf_h_cpr_quad_set_handler (SIM_CPU *current_cpu, UINT cpr, SI *newval) 428 { 429 /* Check the register alignment. */ 430 cpr = check_register_alignment (current_cpu, cpr, 3); 431 432 SET_H_CPR (cpr , newval[0]); 433 SET_H_CPR (cpr + 1, newval[1]); 434 SET_H_CPR (cpr + 2, newval[2]); 435 SET_H_CPR (cpr + 3, newval[3]); 436 } 437 438 /* Cover fns to access the special purpose registers. */ 439 USI 440 frvbf_h_spr_get_handler (SIM_CPU *current_cpu, UINT spr) 441 { 442 /* Check access restrictions. */ 443 frv_check_spr_read_access (current_cpu, spr); 444 445 switch (spr) 446 { 447 case H_SPR_PSR: 448 return spr_psr_get_handler (current_cpu); 449 case H_SPR_TBR: 450 return spr_tbr_get_handler (current_cpu); 451 case H_SPR_BPSR: 452 return spr_bpsr_get_handler (current_cpu); 453 case H_SPR_CCR: 454 return spr_ccr_get_handler (current_cpu); 455 case H_SPR_CCCR: 456 return spr_cccr_get_handler (current_cpu); 457 case H_SPR_SR0: 458 case H_SPR_SR1: 459 case H_SPR_SR2: 460 case H_SPR_SR3: 461 return spr_sr_get_handler (current_cpu, spr); 462 break; 463 default: 464 return CPU (h_spr[spr]); 465 } 466 return 0; 467 } 468 469 void 470 frvbf_h_spr_set_handler (SIM_CPU *current_cpu, UINT spr, USI newval) 471 { 472 FRV_REGISTER_CONTROL *control; 473 USI mask; 474 USI oldval; 475 476 /* Check access restrictions. */ 477 frv_check_spr_write_access (current_cpu, spr); 478 479 /* Only set those fields which are writeable. */ 480 control = CPU_REGISTER_CONTROL (current_cpu); 481 mask = control->spr[spr].read_only_mask; 482 oldval = GET_H_SPR (spr); 483 484 newval = (newval & ~mask) | (oldval & mask); 485 486 /* Some registers are represented by individual components which are 487 referenced more often than the register itself. */ 488 switch (spr) 489 { 490 case H_SPR_PSR: 491 spr_psr_set_handler (current_cpu, newval); 492 break; 493 case H_SPR_TBR: 494 spr_tbr_set_handler (current_cpu, newval); 495 break; 496 case H_SPR_BPSR: 497 spr_bpsr_set_handler (current_cpu, newval); 498 break; 499 case H_SPR_CCR: 500 spr_ccr_set_handler (current_cpu, newval); 501 break; 502 case H_SPR_CCCR: 503 spr_cccr_set_handler (current_cpu, newval); 504 break; 505 case H_SPR_SR0: 506 case H_SPR_SR1: 507 case H_SPR_SR2: 508 case H_SPR_SR3: 509 spr_sr_set_handler (current_cpu, spr, newval); 510 break; 511 case H_SPR_IHSR8: 512 frv_cache_reconfigure (current_cpu, CPU_INSN_CACHE (current_cpu)); 513 break; 514 default: 515 CPU (h_spr[spr]) = newval; 516 break; 517 } 518 } 519 520 /* Cover fns to access the gr_hi and gr_lo registers. */ 521 UHI 522 frvbf_h_gr_hi_get_handler (SIM_CPU *current_cpu, UINT gr) 523 { 524 return (GET_H_GR(gr) >> 16) & 0xffff; 525 } 526 527 void 528 frvbf_h_gr_hi_set_handler (SIM_CPU *current_cpu, UINT gr, UHI newval) 529 { 530 USI value = (GET_H_GR (gr) & 0xffff) | (newval << 16); 531 SET_H_GR (gr, value); 532 } 533 534 UHI 535 frvbf_h_gr_lo_get_handler (SIM_CPU *current_cpu, UINT gr) 536 { 537 return GET_H_GR(gr) & 0xffff; 538 } 539 540 void 541 frvbf_h_gr_lo_set_handler (SIM_CPU *current_cpu, UINT gr, UHI newval) 542 { 543 USI value = (GET_H_GR (gr) & 0xffff0000) | (newval & 0xffff); 544 SET_H_GR (gr, value); 545 } 546 547 /* Cover fns to access the tbr bits. */ 548 USI 549 spr_tbr_get_handler (SIM_CPU *current_cpu) 550 { 551 int tbr = ((GET_H_TBR_TBA () & 0xfffff) << 12) | 552 ((GET_H_TBR_TT () & 0xff) << 4); 553 554 return tbr; 555 } 556 557 void 558 spr_tbr_set_handler (SIM_CPU *current_cpu, USI newval) 559 { 560 int tbr = newval; 561 562 SET_H_TBR_TBA ((tbr >> 12) & 0xfffff) ; 563 SET_H_TBR_TT ((tbr >> 4) & 0xff) ; 564 } 565 566 /* Cover fns to access the bpsr bits. */ 567 USI 568 spr_bpsr_get_handler (SIM_CPU *current_cpu) 569 { 570 int bpsr = ((GET_H_BPSR_BS () & 0x1) << 12) | 571 ((GET_H_BPSR_BET () & 0x1) ); 572 573 return bpsr; 574 } 575 576 void 577 spr_bpsr_set_handler (SIM_CPU *current_cpu, USI newval) 578 { 579 int bpsr = newval; 580 581 SET_H_BPSR_BS ((bpsr >> 12) & 1); 582 SET_H_BPSR_BET ((bpsr ) & 1); 583 } 584 585 /* Cover fns to access the psr bits. */ 586 USI 587 spr_psr_get_handler (SIM_CPU *current_cpu) 588 { 589 int psr = ((GET_H_PSR_IMPLE () & 0xf) << 28) | 590 ((GET_H_PSR_VER () & 0xf) << 24) | 591 ((GET_H_PSR_ICE () & 0x1) << 16) | 592 ((GET_H_PSR_NEM () & 0x1) << 14) | 593 ((GET_H_PSR_CM () & 0x1) << 13) | 594 ((GET_H_PSR_BE () & 0x1) << 12) | 595 ((GET_H_PSR_ESR () & 0x1) << 11) | 596 ((GET_H_PSR_EF () & 0x1) << 8) | 597 ((GET_H_PSR_EM () & 0x1) << 7) | 598 ((GET_H_PSR_PIL () & 0xf) << 3) | 599 ((GET_H_PSR_S () & 0x1) << 2) | 600 ((GET_H_PSR_PS () & 0x1) << 1) | 601 ((GET_H_PSR_ET () & 0x1) ); 602 603 return psr; 604 } 605 606 void 607 spr_psr_set_handler (SIM_CPU *current_cpu, USI newval) 608 { 609 /* The handler for PSR.S references the value of PSR.ESR, so set PSR.S 610 first. */ 611 SET_H_PSR_S ((newval >> 2) & 1); 612 613 SET_H_PSR_IMPLE ((newval >> 28) & 0xf); 614 SET_H_PSR_VER ((newval >> 24) & 0xf); 615 SET_H_PSR_ICE ((newval >> 16) & 1); 616 SET_H_PSR_NEM ((newval >> 14) & 1); 617 SET_H_PSR_CM ((newval >> 13) & 1); 618 SET_H_PSR_BE ((newval >> 12) & 1); 619 SET_H_PSR_ESR ((newval >> 11) & 1); 620 SET_H_PSR_EF ((newval >> 8) & 1); 621 SET_H_PSR_EM ((newval >> 7) & 1); 622 SET_H_PSR_PIL ((newval >> 3) & 0xf); 623 SET_H_PSR_PS ((newval >> 1) & 1); 624 SET_H_PSR_ET ((newval ) & 1); 625 } 626 627 void 628 frvbf_h_psr_s_set_handler (SIM_CPU *current_cpu, BI newval) 629 { 630 /* If switching from user to supervisor mode, or vice-versa, then switch 631 the supervisor/user context. */ 632 int psr_s = GET_H_PSR_S (); 633 if (psr_s != (newval & 1)) 634 { 635 frvbf_switch_supervisor_user_context (current_cpu); 636 CPU (h_psr_s) = newval & 1; 637 } 638 } 639 640 /* Cover fns to access the ccr bits. */ 641 USI 642 spr_ccr_get_handler (SIM_CPU *current_cpu) 643 { 644 int ccr = ((GET_H_ICCR (H_ICCR_ICC3) & 0xf) << 28) | 645 ((GET_H_ICCR (H_ICCR_ICC2) & 0xf) << 24) | 646 ((GET_H_ICCR (H_ICCR_ICC1) & 0xf) << 20) | 647 ((GET_H_ICCR (H_ICCR_ICC0) & 0xf) << 16) | 648 ((GET_H_FCCR (H_FCCR_FCC3) & 0xf) << 12) | 649 ((GET_H_FCCR (H_FCCR_FCC2) & 0xf) << 8) | 650 ((GET_H_FCCR (H_FCCR_FCC1) & 0xf) << 4) | 651 ((GET_H_FCCR (H_FCCR_FCC0) & 0xf) ); 652 653 return ccr; 654 } 655 656 void 657 spr_ccr_set_handler (SIM_CPU *current_cpu, USI newval) 658 { 659 SET_H_ICCR (H_ICCR_ICC3, (newval >> 28) & 0xf); 660 SET_H_ICCR (H_ICCR_ICC2, (newval >> 24) & 0xf); 661 SET_H_ICCR (H_ICCR_ICC1, (newval >> 20) & 0xf); 662 SET_H_ICCR (H_ICCR_ICC0, (newval >> 16) & 0xf); 663 SET_H_FCCR (H_FCCR_FCC3, (newval >> 12) & 0xf); 664 SET_H_FCCR (H_FCCR_FCC2, (newval >> 8) & 0xf); 665 SET_H_FCCR (H_FCCR_FCC1, (newval >> 4) & 0xf); 666 SET_H_FCCR (H_FCCR_FCC0, (newval ) & 0xf); 667 } 668 669 QI 670 frvbf_set_icc_for_shift_right ( 671 SIM_CPU *current_cpu, SI value, SI shift, QI icc 672 ) 673 { 674 /* Set the C flag of the given icc to the logical OR of the bits shifted 675 out. */ 676 int mask = (1 << shift) - 1; 677 if ((value & mask) != 0) 678 return icc | 0x1; 679 680 return icc & 0xe; 681 } 682 683 QI 684 frvbf_set_icc_for_shift_left ( 685 SIM_CPU *current_cpu, SI value, SI shift, QI icc 686 ) 687 { 688 /* Set the V flag of the given icc to the logical OR of the bits shifted 689 out. */ 690 int mask = ((1 << shift) - 1) << (32 - shift); 691 if ((value & mask) != 0) 692 return icc | 0x2; 693 694 return icc & 0xd; 695 } 696 697 /* Cover fns to access the cccr bits. */ 698 USI 699 spr_cccr_get_handler (SIM_CPU *current_cpu) 700 { 701 int cccr = ((GET_H_CCCR (H_CCCR_CC7) & 0x3) << 14) | 702 ((GET_H_CCCR (H_CCCR_CC6) & 0x3) << 12) | 703 ((GET_H_CCCR (H_CCCR_CC5) & 0x3) << 10) | 704 ((GET_H_CCCR (H_CCCR_CC4) & 0x3) << 8) | 705 ((GET_H_CCCR (H_CCCR_CC3) & 0x3) << 6) | 706 ((GET_H_CCCR (H_CCCR_CC2) & 0x3) << 4) | 707 ((GET_H_CCCR (H_CCCR_CC1) & 0x3) << 2) | 708 ((GET_H_CCCR (H_CCCR_CC0) & 0x3) ); 709 710 return cccr; 711 } 712 713 void 714 spr_cccr_set_handler (SIM_CPU *current_cpu, USI newval) 715 { 716 SET_H_CCCR (H_CCCR_CC7, (newval >> 14) & 0x3); 717 SET_H_CCCR (H_CCCR_CC6, (newval >> 12) & 0x3); 718 SET_H_CCCR (H_CCCR_CC5, (newval >> 10) & 0x3); 719 SET_H_CCCR (H_CCCR_CC4, (newval >> 8) & 0x3); 720 SET_H_CCCR (H_CCCR_CC3, (newval >> 6) & 0x3); 721 SET_H_CCCR (H_CCCR_CC2, (newval >> 4) & 0x3); 722 SET_H_CCCR (H_CCCR_CC1, (newval >> 2) & 0x3); 723 SET_H_CCCR (H_CCCR_CC0, (newval ) & 0x3); 724 } 725 726 /* Cover fns to access the sr bits. */ 727 USI 728 spr_sr_get_handler (SIM_CPU *current_cpu, UINT spr) 729 { 730 /* If PSR.ESR is not set, then SR0-3 map onto SGR4-7 which will be GR4-7, 731 otherwise the correct mapping of USG4-7 or SGR4-7 will be in SR0-3. */ 732 int psr_esr = GET_H_PSR_ESR (); 733 if (! psr_esr) 734 return GET_H_GR (4 + (spr - H_SPR_SR0)); 735 736 return CPU (h_spr[spr]); 737 } 738 739 void 740 spr_sr_set_handler (SIM_CPU *current_cpu, UINT spr, USI newval) 741 { 742 /* If PSR.ESR is not set, then SR0-3 map onto SGR4-7 which will be GR4-7, 743 otherwise the correct mapping of USG4-7 or SGR4-7 will be in SR0-3. */ 744 int psr_esr = GET_H_PSR_ESR (); 745 if (! psr_esr) 746 SET_H_GR (4 + (spr - H_SPR_SR0), newval); 747 else 748 CPU (h_spr[spr]) = newval; 749 } 750 751 /* Switch SR0-SR4 with GR4-GR7 if PSR.ESR is set. */ 752 void 753 frvbf_switch_supervisor_user_context (SIM_CPU *current_cpu) 754 { 755 if (GET_H_PSR_ESR ()) 756 { 757 /* We need to be in supervisor mode to swap the registers. Access the 758 PSR.S directly in order to avoid recursive context switches. */ 759 int i; 760 int save_psr_s = CPU (h_psr_s); 761 CPU (h_psr_s) = 1; 762 for (i = 0; i < 4; ++i) 763 { 764 int gr = i + 4; 765 int spr = i + H_SPR_SR0; 766 SI tmp = GET_H_SPR (spr); 767 SET_H_SPR (spr, GET_H_GR (gr)); 768 SET_H_GR (gr, tmp); 769 } 770 CPU (h_psr_s) = save_psr_s; 771 } 772 } 773 774 /* Handle load/store of quad registers. */ 775 void 776 frvbf_load_quad_GR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI targ_ix) 777 { 778 int i; 779 SI value[4]; 780 781 /* Check memory alignment */ 782 address = check_memory_alignment (current_cpu, address, 0xf); 783 784 /* If we need to count cycles, then the cache operation will be 785 initiated from the model profiling functions. 786 See frvbf_model_.... */ 787 if (model_insn) 788 { 789 CPU_LOAD_ADDRESS (current_cpu) = address; 790 CPU_LOAD_LENGTH (current_cpu) = 16; 791 } 792 else 793 { 794 for (i = 0; i < 4; ++i) 795 { 796 value[i] = frvbf_read_mem_SI (current_cpu, pc, address); 797 address += 4; 798 } 799 sim_queue_fn_xi_write (current_cpu, frvbf_h_gr_quad_set_handler, targ_ix, 800 value); 801 } 802 } 803 804 void 805 frvbf_store_quad_GR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI src_ix) 806 { 807 int i; 808 SI value[4]; 809 USI hsr0; 810 811 /* Check register and memory alignment. */ 812 src_ix = check_register_alignment (current_cpu, src_ix, 3); 813 address = check_memory_alignment (current_cpu, address, 0xf); 814 815 for (i = 0; i < 4; ++i) 816 { 817 /* GR0 is always 0. */ 818 if (src_ix == 0) 819 value[i] = 0; 820 else 821 value[i] = GET_H_GR (src_ix + i); 822 } 823 hsr0 = GET_HSR0 (); 824 if (GET_HSR0_DCE (hsr0)) 825 sim_queue_fn_mem_xi_write (current_cpu, frvbf_mem_set_XI, address, value); 826 else 827 sim_queue_mem_xi_write (current_cpu, address, value); 828 } 829 830 void 831 frvbf_load_quad_FRint (SIM_CPU *current_cpu, PCADDR pc, SI address, SI targ_ix) 832 { 833 int i; 834 SI value[4]; 835 836 /* Check memory alignment */ 837 address = check_memory_alignment (current_cpu, address, 0xf); 838 839 /* If we need to count cycles, then the cache operation will be 840 initiated from the model profiling functions. 841 See frvbf_model_.... */ 842 if (model_insn) 843 { 844 CPU_LOAD_ADDRESS (current_cpu) = address; 845 CPU_LOAD_LENGTH (current_cpu) = 16; 846 } 847 else 848 { 849 for (i = 0; i < 4; ++i) 850 { 851 value[i] = frvbf_read_mem_SI (current_cpu, pc, address); 852 address += 4; 853 } 854 sim_queue_fn_xi_write (current_cpu, frvbf_h_fr_quad_set_handler, targ_ix, 855 value); 856 } 857 } 858 859 void 860 frvbf_store_quad_FRint (SIM_CPU *current_cpu, PCADDR pc, SI address, SI src_ix) 861 { 862 int i; 863 SI value[4]; 864 USI hsr0; 865 866 /* Check register and memory alignment. */ 867 src_ix = check_fr_register_alignment (current_cpu, src_ix, 3); 868 address = check_memory_alignment (current_cpu, address, 0xf); 869 870 for (i = 0; i < 4; ++i) 871 value[i] = GET_H_FR (src_ix + i); 872 873 hsr0 = GET_HSR0 (); 874 if (GET_HSR0_DCE (hsr0)) 875 sim_queue_fn_mem_xi_write (current_cpu, frvbf_mem_set_XI, address, value); 876 else 877 sim_queue_mem_xi_write (current_cpu, address, value); 878 } 879 880 void 881 frvbf_load_quad_CPR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI targ_ix) 882 { 883 int i; 884 SI value[4]; 885 886 /* Check memory alignment */ 887 address = check_memory_alignment (current_cpu, address, 0xf); 888 889 /* If we need to count cycles, then the cache operation will be 890 initiated from the model profiling functions. 891 See frvbf_model_.... */ 892 if (model_insn) 893 { 894 CPU_LOAD_ADDRESS (current_cpu) = address; 895 CPU_LOAD_LENGTH (current_cpu) = 16; 896 } 897 else 898 { 899 for (i = 0; i < 4; ++i) 900 { 901 value[i] = frvbf_read_mem_SI (current_cpu, pc, address); 902 address += 4; 903 } 904 sim_queue_fn_xi_write (current_cpu, frvbf_h_cpr_quad_set_handler, targ_ix, 905 value); 906 } 907 } 908 909 void 910 frvbf_store_quad_CPR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI src_ix) 911 { 912 int i; 913 SI value[4]; 914 USI hsr0; 915 916 /* Check register and memory alignment. */ 917 src_ix = check_register_alignment (current_cpu, src_ix, 3); 918 address = check_memory_alignment (current_cpu, address, 0xf); 919 920 for (i = 0; i < 4; ++i) 921 value[i] = GET_H_CPR (src_ix + i); 922 923 hsr0 = GET_HSR0 (); 924 if (GET_HSR0_DCE (hsr0)) 925 sim_queue_fn_mem_xi_write (current_cpu, frvbf_mem_set_XI, address, value); 926 else 927 sim_queue_mem_xi_write (current_cpu, address, value); 928 } 929 930 void 931 frvbf_signed_integer_divide ( 932 SIM_CPU *current_cpu, SI arg1, SI arg2, int target_index, int non_excepting 933 ) 934 { 935 enum frv_dtt dtt = FRV_DTT_NO_EXCEPTION; 936 if (arg1 == 0x80000000 && arg2 == -1) 937 { 938 /* 0x80000000/(-1) must result in 0x7fffffff when ISR.EDE is set 939 otherwise it may result in 0x7fffffff (sparc compatibility) or 940 0x80000000 (C language compatibility). */ 941 USI isr; 942 dtt = FRV_DTT_OVERFLOW; 943 944 isr = GET_ISR (); 945 if (GET_ISR_EDE (isr)) 946 sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index, 947 0x7fffffff); 948 else 949 sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index, 950 0x80000000); 951 frvbf_force_update (current_cpu); /* Force update of target register. */ 952 } 953 else if (arg2 == 0) 954 dtt = FRV_DTT_DIVISION_BY_ZERO; 955 else 956 sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index, 957 arg1 / arg2); 958 959 /* Check for exceptions. */ 960 if (dtt != FRV_DTT_NO_EXCEPTION) 961 dtt = frvbf_division_exception (current_cpu, dtt, target_index, 962 non_excepting); 963 if (non_excepting && dtt == FRV_DTT_NO_EXCEPTION) 964 { 965 /* Non excepting instruction. Clear the NE flag for the target 966 register. */ 967 SI NE_flags[2]; 968 GET_NE_FLAGS (NE_flags, H_SPR_GNER0); 969 CLEAR_NE_FLAG (NE_flags, target_index); 970 SET_NE_FLAGS (H_SPR_GNER0, NE_flags); 971 } 972 } 973 974 void 975 frvbf_unsigned_integer_divide ( 976 SIM_CPU *current_cpu, USI arg1, USI arg2, int target_index, int non_excepting 977 ) 978 { 979 if (arg2 == 0) 980 frvbf_division_exception (current_cpu, FRV_DTT_DIVISION_BY_ZERO, 981 target_index, non_excepting); 982 else 983 { 984 sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index, 985 arg1 / arg2); 986 if (non_excepting) 987 { 988 /* Non excepting instruction. Clear the NE flag for the target 989 register. */ 990 SI NE_flags[2]; 991 GET_NE_FLAGS (NE_flags, H_SPR_GNER0); 992 CLEAR_NE_FLAG (NE_flags, target_index); 993 SET_NE_FLAGS (H_SPR_GNER0, NE_flags); 994 } 995 } 996 } 997 998 /* Clear accumulators. */ 999 void 1000 frvbf_clear_accumulators (SIM_CPU *current_cpu, SI acc_ix, int A) 1001 { 1002 SIM_DESC sd = CPU_STATE (current_cpu); 1003 int acc_mask = 1004 (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr500) ? 7 : 1005 (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) ? 7 : 1006 (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450) ? 11 : 1007 (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400) ? 3 : 1008 63; 1009 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu); 1010 1011 ps->mclracc_acc = acc_ix; 1012 ps->mclracc_A = A; 1013 if (A == 0 || acc_ix != 0) /* Clear 1 accumuator? */ 1014 { 1015 /* This instruction is a nop if the referenced accumulator is not 1016 implemented. */ 1017 if ((acc_ix & acc_mask) == acc_ix) 1018 sim_queue_fn_di_write (current_cpu, frvbf_h_acc40S_set, acc_ix, 0); 1019 } 1020 else 1021 { 1022 /* Clear all implemented accumulators. */ 1023 int i; 1024 for (i = 0; i <= acc_mask; ++i) 1025 if ((i & acc_mask) == i) 1026 sim_queue_fn_di_write (current_cpu, frvbf_h_acc40S_set, i, 0); 1027 } 1028 } 1029 1030 /* Functions to aid insn semantics. */ 1031 1032 /* Compute the result of the SCAN and SCANI insns after the shift and xor. */ 1033 SI 1034 frvbf_scan_result (SIM_CPU *current_cpu, SI value) 1035 { 1036 SI i; 1037 SI mask; 1038 1039 if (value == 0) 1040 return 63; 1041 1042 /* Find the position of the first non-zero bit. 1043 The loop will terminate since there is guaranteed to be at least one 1044 non-zero bit. */ 1045 mask = 1 << (sizeof (mask) * 8 - 1); 1046 for (i = 0; (value & mask) == 0; ++i) 1047 value <<= 1; 1048 1049 return i; 1050 } 1051 1052 /* Compute the result of the cut insns. */ 1053 SI 1054 frvbf_cut (SIM_CPU *current_cpu, SI reg1, SI reg2, SI cut_point) 1055 { 1056 SI result; 1057 cut_point &= 0x3f; 1058 if (cut_point < 32) 1059 { 1060 result = reg1 << cut_point; 1061 result |= (reg2 >> (32 - cut_point)) & ((1 << cut_point) - 1); 1062 } 1063 else 1064 result = reg2 << (cut_point - 32); 1065 1066 return result; 1067 } 1068 1069 /* Compute the result of the cut insns. */ 1070 SI 1071 frvbf_media_cut (SIM_CPU *current_cpu, DI acc, SI cut_point) 1072 { 1073 /* The cut point is the lower 6 bits (signed) of what we are passed. */ 1074 cut_point = cut_point << 26 >> 26; 1075 1076 /* The cut_point is relative to bit 40 of 64 bits. */ 1077 if (cut_point >= 0) 1078 return (acc << (cut_point + 24)) >> 32; 1079 1080 /* Extend the sign bit (bit 40) for negative cuts. */ 1081 if (cut_point == -32) 1082 return (acc << 24) >> 63; /* Special case for full shiftout. */ 1083 1084 return (acc << 24) >> (32 + -cut_point); 1085 } 1086 1087 /* Compute the result of the cut insns. */ 1088 SI 1089 frvbf_media_cut_ss (SIM_CPU *current_cpu, DI acc, SI cut_point) 1090 { 1091 /* The cut point is the lower 6 bits (signed) of what we are passed. */ 1092 cut_point = cut_point << 26 >> 26; 1093 1094 if (cut_point >= 0) 1095 { 1096 /* The cut_point is relative to bit 40 of 64 bits. */ 1097 DI shifted = acc << (cut_point + 24); 1098 DI unshifted = shifted >> (cut_point + 24); 1099 1100 /* The result will be saturated if significant bits are shifted out. */ 1101 if (unshifted != acc) 1102 { 1103 if (acc < 0) 1104 return 0x80000000; 1105 return 0x7fffffff; 1106 } 1107 } 1108 1109 /* The result will not be saturated, so use the code for the normal cut. */ 1110 return frvbf_media_cut (current_cpu, acc, cut_point); 1111 } 1112 1113 /* Compute the result of int accumulator cut (SCUTSS). */ 1114 SI 1115 frvbf_iacc_cut (SIM_CPU *current_cpu, DI acc, SI cut_point) 1116 { 1117 DI lower, upper; 1118 1119 /* The cut point is the lower 7 bits (signed) of what we are passed. */ 1120 cut_point = cut_point << 25 >> 25; 1121 1122 /* Conceptually, the operation is on a 128-bit sign-extension of ACC. 1123 The top bit of the return value corresponds to bit (63 - CUT_POINT) 1124 of this 128-bit value. 1125 1126 Since we can't deal with 128-bit values very easily, convert the 1127 operation into an equivalent 64-bit one. */ 1128 if (cut_point < 0) 1129 { 1130 /* Avoid an undefined shift operation. */ 1131 if (cut_point == -64) 1132 acc >>= 63; 1133 else 1134 acc >>= -cut_point; 1135 cut_point = 0; 1136 } 1137 1138 /* Get the shifted but unsaturated result. Set LOWER to the lowest 1139 32 bits of the result and UPPER to the result >> 31. */ 1140 if (cut_point < 32) 1141 { 1142 /* The cut loses the (32 - CUT_POINT) least significant bits. 1143 Round the result up if the most significant of these lost bits 1144 is 1. */ 1145 lower = acc >> (32 - cut_point); 1146 if (lower < 0x7fffffff) 1147 if (acc & LSBIT64 (32 - cut_point - 1)) 1148 lower++; 1149 upper = lower >> 31; 1150 } 1151 else 1152 { 1153 lower = acc << (cut_point - 32); 1154 upper = acc >> (63 - cut_point); 1155 } 1156 1157 /* Saturate the result. */ 1158 if (upper < -1) 1159 return ~0x7fffffff; 1160 else if (upper > 0) 1161 return 0x7fffffff; 1162 else 1163 return lower; 1164 } 1165 1166 /* Compute the result of shift-left-arithmetic-with-saturation (SLASS). */ 1167 SI 1168 frvbf_shift_left_arith_saturate (SIM_CPU *current_cpu, SI arg1, SI arg2) 1169 { 1170 int neg_arg1; 1171 1172 /* FIXME: what to do with negative shift amt? */ 1173 if (arg2 <= 0) 1174 return arg1; 1175 1176 if (arg1 == 0) 1177 return 0; 1178 1179 /* Signed shift by 31 or greater saturates by definition. */ 1180 if (arg2 >= 31) 1181 { 1182 if (arg1 > 0) 1183 return (SI) 0x7fffffff; 1184 else 1185 return (SI) 0x80000000; 1186 } 1187 1188 /* OK, arg2 is between 1 and 31. */ 1189 neg_arg1 = (arg1 < 0); 1190 do { 1191 arg1 <<= 1; 1192 /* Check for sign bit change (saturation). */ 1193 if (neg_arg1 && (arg1 >= 0)) 1194 return (SI) 0x80000000; 1195 else if (!neg_arg1 && (arg1 < 0)) 1196 return (SI) 0x7fffffff; 1197 } while (--arg2 > 0); 1198 1199 return arg1; 1200 } 1201 1202 /* Simulate the media custom insns. */ 1203 void 1204 frvbf_media_cop (SIM_CPU *current_cpu, int cop_num) 1205 { 1206 /* The semantics of the insn are a nop, since it is implementation defined. 1207 We do need to check whether it's implemented and set up for MTRAP 1208 if it's not. */ 1209 USI msr0 = GET_MSR (0); 1210 if (GET_MSR_EMCI (msr0) == 0) 1211 { 1212 /* no interrupt queued at this time. */ 1213 frv_set_mp_exception_registers (current_cpu, MTT_UNIMPLEMENTED_MPOP, 0); 1214 } 1215 } 1216 1217 /* Simulate the media average (MAVEH) insn. */ 1218 static HI 1219 do_media_average (SIM_CPU *current_cpu, HI arg1, HI arg2) 1220 { 1221 SIM_DESC sd = CPU_STATE (current_cpu); 1222 SI sum = (arg1 + arg2); 1223 HI result = sum >> 1; 1224 int rounding_value; 1225 1226 /* On fr4xx and fr550, check the rounding mode. On other machines 1227 rounding is always toward negative infinity and the result is 1228 already correctly rounded. */ 1229 switch (STATE_ARCHITECTURE (sd)->mach) 1230 { 1231 /* Need to check rounding mode. */ 1232 case bfd_mach_fr400: 1233 case bfd_mach_fr450: 1234 case bfd_mach_fr550: 1235 /* Check whether rounding will be required. Rounding will be required 1236 if the sum is an odd number. */ 1237 rounding_value = sum & 1; 1238 if (rounding_value) 1239 { 1240 USI msr0 = GET_MSR (0); 1241 /* Check MSR0.SRDAV to determine which bits control the rounding. */ 1242 if (GET_MSR_SRDAV (msr0)) 1243 { 1244 /* MSR0.RD controls rounding. */ 1245 switch (GET_MSR_RD (msr0)) 1246 { 1247 case 0: 1248 /* Round to nearest. */ 1249 if (result >= 0) 1250 ++result; 1251 break; 1252 case 1: 1253 /* Round toward 0. */ 1254 if (result < 0) 1255 ++result; 1256 break; 1257 case 2: 1258 /* Round toward positive infinity. */ 1259 ++result; 1260 break; 1261 case 3: 1262 /* Round toward negative infinity. The result is already 1263 correctly rounded. */ 1264 break; 1265 default: 1266 abort (); 1267 break; 1268 } 1269 } 1270 else 1271 { 1272 /* MSR0.RDAV controls rounding. If set, round toward positive 1273 infinity. Otherwise the result is already rounded correctly 1274 toward negative infinity. */ 1275 if (GET_MSR_RDAV (msr0)) 1276 ++result; 1277 } 1278 } 1279 break; 1280 default: 1281 break; 1282 } 1283 1284 return result; 1285 } 1286 1287 SI 1288 frvbf_media_average (SIM_CPU *current_cpu, SI reg1, SI reg2) 1289 { 1290 SI result; 1291 result = do_media_average (current_cpu, reg1 & 0xffff, reg2 & 0xffff); 1292 result &= 0xffff; 1293 result |= do_media_average (current_cpu, (reg1 >> 16) & 0xffff, 1294 (reg2 >> 16) & 0xffff) << 16; 1295 return result; 1296 } 1297 1298 /* Maintain a flag in order to know when to write the address of the next 1299 VLIW instruction into the LR register. Used by JMPL. JMPIL, and CALL. */ 1300 void 1301 frvbf_set_write_next_vliw_addr_to_LR (SIM_CPU *current_cpu, int value) 1302 { 1303 frvbf_write_next_vliw_addr_to_LR = value; 1304 } 1305 1306 void 1307 frvbf_set_ne_index (SIM_CPU *current_cpu, int index) 1308 { 1309 USI NE_flags[2]; 1310 1311 /* Save the target register so interrupt processing can set its NE flag 1312 in the event of an exception. */ 1313 frv_interrupt_state.ne_index = index; 1314 1315 /* Clear the NE flag of the target register. It will be reset if necessary 1316 in the event of an exception. */ 1317 GET_NE_FLAGS (NE_flags, H_SPR_FNER0); 1318 CLEAR_NE_FLAG (NE_flags, index); 1319 SET_NE_FLAGS (H_SPR_FNER0, NE_flags); 1320 } 1321 1322 void 1323 frvbf_force_update (SIM_CPU *current_cpu) 1324 { 1325 CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (current_cpu); 1326 int ix = CGEN_WRITE_QUEUE_INDEX (q); 1327 if (ix > 0) 1328 { 1329 CGEN_WRITE_QUEUE_ELEMENT *item = CGEN_WRITE_QUEUE_ELEMENT (q, ix - 1); 1330 item->flags |= FRV_WRITE_QUEUE_FORCE_WRITE; 1331 } 1332 } 1333 1334 /* Condition code logic. */ 1335 enum cr_ops { 1336 andcr, orcr, xorcr, nandcr, norcr, andncr, orncr, nandncr, norncr, 1337 num_cr_ops 1338 }; 1339 1340 enum cr_result {cr_undefined, cr_undefined1, cr_false, cr_true}; 1341 1342 static enum cr_result 1343 cr_logic[num_cr_ops][4][4] = { 1344 /* andcr */ 1345 { 1346 /* undefined undefined false true */ 1347 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1348 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1349 /* false */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1350 /* true */ {cr_undefined, cr_undefined, cr_false, cr_true } 1351 }, 1352 /* orcr */ 1353 { 1354 /* undefined undefined false true */ 1355 /* undefined */ {cr_undefined, cr_undefined, cr_false, cr_true }, 1356 /* undefined */ {cr_undefined, cr_undefined, cr_false, cr_true }, 1357 /* false */ {cr_false, cr_false, cr_false, cr_true }, 1358 /* true */ {cr_true, cr_true, cr_true, cr_true } 1359 }, 1360 /* xorcr */ 1361 { 1362 /* undefined undefined false true */ 1363 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1364 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1365 /* false */ {cr_undefined, cr_undefined, cr_false, cr_true }, 1366 /* true */ {cr_true, cr_true, cr_true, cr_false } 1367 }, 1368 /* nandcr */ 1369 { 1370 /* undefined undefined false true */ 1371 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1372 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1373 /* false */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1374 /* true */ {cr_undefined, cr_undefined, cr_true, cr_false } 1375 }, 1376 /* norcr */ 1377 { 1378 /* undefined undefined false true */ 1379 /* undefined */ {cr_undefined, cr_undefined, cr_true, cr_false }, 1380 /* undefined */ {cr_undefined, cr_undefined, cr_true, cr_false }, 1381 /* false */ {cr_true, cr_true, cr_true, cr_false }, 1382 /* true */ {cr_false, cr_false, cr_false, cr_false } 1383 }, 1384 /* andncr */ 1385 { 1386 /* undefined undefined false true */ 1387 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1388 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1389 /* false */ {cr_undefined, cr_undefined, cr_false, cr_true }, 1390 /* true */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined} 1391 }, 1392 /* orncr */ 1393 { 1394 /* undefined undefined false true */ 1395 /* undefined */ {cr_undefined, cr_undefined, cr_false, cr_true }, 1396 /* undefined */ {cr_undefined, cr_undefined, cr_false, cr_true }, 1397 /* false */ {cr_true, cr_true, cr_true, cr_true }, 1398 /* true */ {cr_false, cr_false, cr_false, cr_true } 1399 }, 1400 /* nandncr */ 1401 { 1402 /* undefined undefined false true */ 1403 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1404 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1405 /* false */ {cr_undefined, cr_undefined, cr_true, cr_false }, 1406 /* true */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined} 1407 }, 1408 /* norncr */ 1409 { 1410 /* undefined undefined false true */ 1411 /* undefined */ {cr_undefined, cr_undefined, cr_true, cr_false }, 1412 /* undefined */ {cr_undefined, cr_undefined, cr_true, cr_false }, 1413 /* false */ {cr_false, cr_false, cr_false, cr_false }, 1414 /* true */ {cr_true, cr_true, cr_true, cr_false } 1415 } 1416 }; 1417 1418 UQI 1419 frvbf_cr_logic (SIM_CPU *current_cpu, SI operation, UQI arg1, UQI arg2) 1420 { 1421 return cr_logic[operation][arg1][arg2]; 1422 } 1423 1424 /* Cache Manipulation. */ 1425 void 1426 frvbf_insn_cache_preload (SIM_CPU *current_cpu, SI address, USI length, int lock) 1427 { 1428 /* If we need to count cycles, then the cache operation will be 1429 initiated from the model profiling functions. 1430 See frvbf_model_.... */ 1431 int hsr0 = GET_HSR0 (); 1432 if (GET_HSR0_ICE (hsr0)) 1433 { 1434 if (model_insn) 1435 { 1436 CPU_LOAD_ADDRESS (current_cpu) = address; 1437 CPU_LOAD_LENGTH (current_cpu) = length; 1438 CPU_LOAD_LOCK (current_cpu) = lock; 1439 } 1440 else 1441 { 1442 FRV_CACHE *cache = CPU_INSN_CACHE (current_cpu); 1443 frv_cache_preload (cache, address, length, lock); 1444 } 1445 } 1446 } 1447 1448 void 1449 frvbf_data_cache_preload (SIM_CPU *current_cpu, SI address, USI length, int lock) 1450 { 1451 /* If we need to count cycles, then the cache operation will be 1452 initiated from the model profiling functions. 1453 See frvbf_model_.... */ 1454 int hsr0 = GET_HSR0 (); 1455 if (GET_HSR0_DCE (hsr0)) 1456 { 1457 if (model_insn) 1458 { 1459 CPU_LOAD_ADDRESS (current_cpu) = address; 1460 CPU_LOAD_LENGTH (current_cpu) = length; 1461 CPU_LOAD_LOCK (current_cpu) = lock; 1462 } 1463 else 1464 { 1465 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); 1466 frv_cache_preload (cache, address, length, lock); 1467 } 1468 } 1469 } 1470 1471 void 1472 frvbf_insn_cache_unlock (SIM_CPU *current_cpu, SI address) 1473 { 1474 /* If we need to count cycles, then the cache operation will be 1475 initiated from the model profiling functions. 1476 See frvbf_model_.... */ 1477 int hsr0 = GET_HSR0 (); 1478 if (GET_HSR0_ICE (hsr0)) 1479 { 1480 if (model_insn) 1481 CPU_LOAD_ADDRESS (current_cpu) = address; 1482 else 1483 { 1484 FRV_CACHE *cache = CPU_INSN_CACHE (current_cpu); 1485 frv_cache_unlock (cache, address); 1486 } 1487 } 1488 } 1489 1490 void 1491 frvbf_data_cache_unlock (SIM_CPU *current_cpu, SI address) 1492 { 1493 /* If we need to count cycles, then the cache operation will be 1494 initiated from the model profiling functions. 1495 See frvbf_model_.... */ 1496 int hsr0 = GET_HSR0 (); 1497 if (GET_HSR0_DCE (hsr0)) 1498 { 1499 if (model_insn) 1500 CPU_LOAD_ADDRESS (current_cpu) = address; 1501 else 1502 { 1503 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); 1504 frv_cache_unlock (cache, address); 1505 } 1506 } 1507 } 1508 1509 void 1510 frvbf_insn_cache_invalidate (SIM_CPU *current_cpu, SI address, int all) 1511 { 1512 /* Make sure the insn was specified properly. -1 will be passed for ALL 1513 for a icei with A=0. */ 1514 if (all == -1) 1515 { 1516 frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION); 1517 return; 1518 } 1519 1520 /* If we need to count cycles, then the cache operation will be 1521 initiated from the model profiling functions. 1522 See frvbf_model_.... */ 1523 if (model_insn) 1524 { 1525 /* Record the all-entries flag for use in profiling. */ 1526 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu); 1527 ps->all_cache_entries = all; 1528 CPU_LOAD_ADDRESS (current_cpu) = address; 1529 } 1530 else 1531 { 1532 FRV_CACHE *cache = CPU_INSN_CACHE (current_cpu); 1533 if (all) 1534 frv_cache_invalidate_all (cache, 0/* flush? */); 1535 else 1536 frv_cache_invalidate (cache, address, 0/* flush? */); 1537 } 1538 } 1539 1540 void 1541 frvbf_data_cache_invalidate (SIM_CPU *current_cpu, SI address, int all) 1542 { 1543 /* Make sure the insn was specified properly. -1 will be passed for ALL 1544 for a dcei with A=0. */ 1545 if (all == -1) 1546 { 1547 frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION); 1548 return; 1549 } 1550 1551 /* If we need to count cycles, then the cache operation will be 1552 initiated from the model profiling functions. 1553 See frvbf_model_.... */ 1554 if (model_insn) 1555 { 1556 /* Record the all-entries flag for use in profiling. */ 1557 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu); 1558 ps->all_cache_entries = all; 1559 CPU_LOAD_ADDRESS (current_cpu) = address; 1560 } 1561 else 1562 { 1563 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); 1564 if (all) 1565 frv_cache_invalidate_all (cache, 0/* flush? */); 1566 else 1567 frv_cache_invalidate (cache, address, 0/* flush? */); 1568 } 1569 } 1570 1571 void 1572 frvbf_data_cache_flush (SIM_CPU *current_cpu, SI address, int all) 1573 { 1574 /* Make sure the insn was specified properly. -1 will be passed for ALL 1575 for a dcef with A=0. */ 1576 if (all == -1) 1577 { 1578 frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION); 1579 return; 1580 } 1581 1582 /* If we need to count cycles, then the cache operation will be 1583 initiated from the model profiling functions. 1584 See frvbf_model_.... */ 1585 if (model_insn) 1586 { 1587 /* Record the all-entries flag for use in profiling. */ 1588 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu); 1589 ps->all_cache_entries = all; 1590 CPU_LOAD_ADDRESS (current_cpu) = address; 1591 } 1592 else 1593 { 1594 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); 1595 if (all) 1596 frv_cache_invalidate_all (cache, 1/* flush? */); 1597 else 1598 frv_cache_invalidate (cache, address, 1/* flush? */); 1599 } 1600 } 1601