1 /* frv simulator support code 2 Copyright (C) 1998-2023 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 "gdb/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 int ccr = newval; 660 661 SET_H_ICCR (H_ICCR_ICC3, (newval >> 28) & 0xf); 662 SET_H_ICCR (H_ICCR_ICC2, (newval >> 24) & 0xf); 663 SET_H_ICCR (H_ICCR_ICC1, (newval >> 20) & 0xf); 664 SET_H_ICCR (H_ICCR_ICC0, (newval >> 16) & 0xf); 665 SET_H_FCCR (H_FCCR_FCC3, (newval >> 12) & 0xf); 666 SET_H_FCCR (H_FCCR_FCC2, (newval >> 8) & 0xf); 667 SET_H_FCCR (H_FCCR_FCC1, (newval >> 4) & 0xf); 668 SET_H_FCCR (H_FCCR_FCC0, (newval ) & 0xf); 669 } 670 671 QI 672 frvbf_set_icc_for_shift_right ( 673 SIM_CPU *current_cpu, SI value, SI shift, QI icc 674 ) 675 { 676 /* Set the C flag of the given icc to the logical OR of the bits shifted 677 out. */ 678 int mask = (1 << shift) - 1; 679 if ((value & mask) != 0) 680 return icc | 0x1; 681 682 return icc & 0xe; 683 } 684 685 QI 686 frvbf_set_icc_for_shift_left ( 687 SIM_CPU *current_cpu, SI value, SI shift, QI icc 688 ) 689 { 690 /* Set the V flag of the given icc to the logical OR of the bits shifted 691 out. */ 692 int mask = ((1 << shift) - 1) << (32 - shift); 693 if ((value & mask) != 0) 694 return icc | 0x2; 695 696 return icc & 0xd; 697 } 698 699 /* Cover fns to access the cccr bits. */ 700 USI 701 spr_cccr_get_handler (SIM_CPU *current_cpu) 702 { 703 int cccr = ((GET_H_CCCR (H_CCCR_CC7) & 0x3) << 14) | 704 ((GET_H_CCCR (H_CCCR_CC6) & 0x3) << 12) | 705 ((GET_H_CCCR (H_CCCR_CC5) & 0x3) << 10) | 706 ((GET_H_CCCR (H_CCCR_CC4) & 0x3) << 8) | 707 ((GET_H_CCCR (H_CCCR_CC3) & 0x3) << 6) | 708 ((GET_H_CCCR (H_CCCR_CC2) & 0x3) << 4) | 709 ((GET_H_CCCR (H_CCCR_CC1) & 0x3) << 2) | 710 ((GET_H_CCCR (H_CCCR_CC0) & 0x3) ); 711 712 return cccr; 713 } 714 715 void 716 spr_cccr_set_handler (SIM_CPU *current_cpu, USI newval) 717 { 718 int cccr = newval; 719 720 SET_H_CCCR (H_CCCR_CC7, (newval >> 14) & 0x3); 721 SET_H_CCCR (H_CCCR_CC6, (newval >> 12) & 0x3); 722 SET_H_CCCR (H_CCCR_CC5, (newval >> 10) & 0x3); 723 SET_H_CCCR (H_CCCR_CC4, (newval >> 8) & 0x3); 724 SET_H_CCCR (H_CCCR_CC3, (newval >> 6) & 0x3); 725 SET_H_CCCR (H_CCCR_CC2, (newval >> 4) & 0x3); 726 SET_H_CCCR (H_CCCR_CC1, (newval >> 2) & 0x3); 727 SET_H_CCCR (H_CCCR_CC0, (newval ) & 0x3); 728 } 729 730 /* Cover fns to access the sr bits. */ 731 USI 732 spr_sr_get_handler (SIM_CPU *current_cpu, UINT spr) 733 { 734 /* If PSR.ESR is not set, then SR0-3 map onto SGR4-7 which will be GR4-7, 735 otherwise the correct mapping of USG4-7 or SGR4-7 will be in SR0-3. */ 736 int psr_esr = GET_H_PSR_ESR (); 737 if (! psr_esr) 738 return GET_H_GR (4 + (spr - H_SPR_SR0)); 739 740 return CPU (h_spr[spr]); 741 } 742 743 void 744 spr_sr_set_handler (SIM_CPU *current_cpu, UINT spr, USI newval) 745 { 746 /* If PSR.ESR is not set, then SR0-3 map onto SGR4-7 which will be GR4-7, 747 otherwise the correct mapping of USG4-7 or SGR4-7 will be in SR0-3. */ 748 int psr_esr = GET_H_PSR_ESR (); 749 if (! psr_esr) 750 SET_H_GR (4 + (spr - H_SPR_SR0), newval); 751 else 752 CPU (h_spr[spr]) = newval; 753 } 754 755 /* Switch SR0-SR4 with GR4-GR7 if PSR.ESR is set. */ 756 void 757 frvbf_switch_supervisor_user_context (SIM_CPU *current_cpu) 758 { 759 if (GET_H_PSR_ESR ()) 760 { 761 /* We need to be in supervisor mode to swap the registers. Access the 762 PSR.S directly in order to avoid recursive context switches. */ 763 int i; 764 int save_psr_s = CPU (h_psr_s); 765 CPU (h_psr_s) = 1; 766 for (i = 0; i < 4; ++i) 767 { 768 int gr = i + 4; 769 int spr = i + H_SPR_SR0; 770 SI tmp = GET_H_SPR (spr); 771 SET_H_SPR (spr, GET_H_GR (gr)); 772 SET_H_GR (gr, tmp); 773 } 774 CPU (h_psr_s) = save_psr_s; 775 } 776 } 777 778 /* Handle load/store of quad registers. */ 779 void 780 frvbf_load_quad_GR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI targ_ix) 781 { 782 int i; 783 SI value[4]; 784 785 /* Check memory alignment */ 786 address = check_memory_alignment (current_cpu, address, 0xf); 787 788 /* If we need to count cycles, then the cache operation will be 789 initiated from the model profiling functions. 790 See frvbf_model_.... */ 791 if (model_insn) 792 { 793 CPU_LOAD_ADDRESS (current_cpu) = address; 794 CPU_LOAD_LENGTH (current_cpu) = 16; 795 } 796 else 797 { 798 for (i = 0; i < 4; ++i) 799 { 800 value[i] = frvbf_read_mem_SI (current_cpu, pc, address); 801 address += 4; 802 } 803 sim_queue_fn_xi_write (current_cpu, frvbf_h_gr_quad_set_handler, targ_ix, 804 value); 805 } 806 } 807 808 void 809 frvbf_store_quad_GR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI src_ix) 810 { 811 int i; 812 SI value[4]; 813 USI hsr0; 814 815 /* Check register and memory alignment. */ 816 src_ix = check_register_alignment (current_cpu, src_ix, 3); 817 address = check_memory_alignment (current_cpu, address, 0xf); 818 819 for (i = 0; i < 4; ++i) 820 { 821 /* GR0 is always 0. */ 822 if (src_ix == 0) 823 value[i] = 0; 824 else 825 value[i] = GET_H_GR (src_ix + i); 826 } 827 hsr0 = GET_HSR0 (); 828 if (GET_HSR0_DCE (hsr0)) 829 sim_queue_fn_mem_xi_write (current_cpu, frvbf_mem_set_XI, address, value); 830 else 831 sim_queue_mem_xi_write (current_cpu, address, value); 832 } 833 834 void 835 frvbf_load_quad_FRint (SIM_CPU *current_cpu, PCADDR pc, SI address, SI targ_ix) 836 { 837 int i; 838 SI value[4]; 839 840 /* Check memory alignment */ 841 address = check_memory_alignment (current_cpu, address, 0xf); 842 843 /* If we need to count cycles, then the cache operation will be 844 initiated from the model profiling functions. 845 See frvbf_model_.... */ 846 if (model_insn) 847 { 848 CPU_LOAD_ADDRESS (current_cpu) = address; 849 CPU_LOAD_LENGTH (current_cpu) = 16; 850 } 851 else 852 { 853 for (i = 0; i < 4; ++i) 854 { 855 value[i] = frvbf_read_mem_SI (current_cpu, pc, address); 856 address += 4; 857 } 858 sim_queue_fn_xi_write (current_cpu, frvbf_h_fr_quad_set_handler, targ_ix, 859 value); 860 } 861 } 862 863 void 864 frvbf_store_quad_FRint (SIM_CPU *current_cpu, PCADDR pc, SI address, SI src_ix) 865 { 866 int i; 867 SI value[4]; 868 USI hsr0; 869 870 /* Check register and memory alignment. */ 871 src_ix = check_fr_register_alignment (current_cpu, src_ix, 3); 872 address = check_memory_alignment (current_cpu, address, 0xf); 873 874 for (i = 0; i < 4; ++i) 875 value[i] = GET_H_FR (src_ix + i); 876 877 hsr0 = GET_HSR0 (); 878 if (GET_HSR0_DCE (hsr0)) 879 sim_queue_fn_mem_xi_write (current_cpu, frvbf_mem_set_XI, address, value); 880 else 881 sim_queue_mem_xi_write (current_cpu, address, value); 882 } 883 884 void 885 frvbf_load_quad_CPR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI targ_ix) 886 { 887 int i; 888 SI value[4]; 889 890 /* Check memory alignment */ 891 address = check_memory_alignment (current_cpu, address, 0xf); 892 893 /* If we need to count cycles, then the cache operation will be 894 initiated from the model profiling functions. 895 See frvbf_model_.... */ 896 if (model_insn) 897 { 898 CPU_LOAD_ADDRESS (current_cpu) = address; 899 CPU_LOAD_LENGTH (current_cpu) = 16; 900 } 901 else 902 { 903 for (i = 0; i < 4; ++i) 904 { 905 value[i] = frvbf_read_mem_SI (current_cpu, pc, address); 906 address += 4; 907 } 908 sim_queue_fn_xi_write (current_cpu, frvbf_h_cpr_quad_set_handler, targ_ix, 909 value); 910 } 911 } 912 913 void 914 frvbf_store_quad_CPR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI src_ix) 915 { 916 int i; 917 SI value[4]; 918 USI hsr0; 919 920 /* Check register and memory alignment. */ 921 src_ix = check_register_alignment (current_cpu, src_ix, 3); 922 address = check_memory_alignment (current_cpu, address, 0xf); 923 924 for (i = 0; i < 4; ++i) 925 value[i] = GET_H_CPR (src_ix + i); 926 927 hsr0 = GET_HSR0 (); 928 if (GET_HSR0_DCE (hsr0)) 929 sim_queue_fn_mem_xi_write (current_cpu, frvbf_mem_set_XI, address, value); 930 else 931 sim_queue_mem_xi_write (current_cpu, address, value); 932 } 933 934 void 935 frvbf_signed_integer_divide ( 936 SIM_CPU *current_cpu, SI arg1, SI arg2, int target_index, int non_excepting 937 ) 938 { 939 enum frv_dtt dtt = FRV_DTT_NO_EXCEPTION; 940 if (arg1 == 0x80000000 && arg2 == -1) 941 { 942 /* 0x80000000/(-1) must result in 0x7fffffff when ISR.EDE is set 943 otherwise it may result in 0x7fffffff (sparc compatibility) or 944 0x80000000 (C language compatibility). */ 945 USI isr; 946 dtt = FRV_DTT_OVERFLOW; 947 948 isr = GET_ISR (); 949 if (GET_ISR_EDE (isr)) 950 sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index, 951 0x7fffffff); 952 else 953 sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index, 954 0x80000000); 955 frvbf_force_update (current_cpu); /* Force update of target register. */ 956 } 957 else if (arg2 == 0) 958 dtt = FRV_DTT_DIVISION_BY_ZERO; 959 else 960 sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index, 961 arg1 / arg2); 962 963 /* Check for exceptions. */ 964 if (dtt != FRV_DTT_NO_EXCEPTION) 965 dtt = frvbf_division_exception (current_cpu, dtt, target_index, 966 non_excepting); 967 if (non_excepting && dtt == FRV_DTT_NO_EXCEPTION) 968 { 969 /* Non excepting instruction. Clear the NE flag for the target 970 register. */ 971 SI NE_flags[2]; 972 GET_NE_FLAGS (NE_flags, H_SPR_GNER0); 973 CLEAR_NE_FLAG (NE_flags, target_index); 974 SET_NE_FLAGS (H_SPR_GNER0, NE_flags); 975 } 976 } 977 978 void 979 frvbf_unsigned_integer_divide ( 980 SIM_CPU *current_cpu, USI arg1, USI arg2, int target_index, int non_excepting 981 ) 982 { 983 if (arg2 == 0) 984 frvbf_division_exception (current_cpu, FRV_DTT_DIVISION_BY_ZERO, 985 target_index, non_excepting); 986 else 987 { 988 sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index, 989 arg1 / arg2); 990 if (non_excepting) 991 { 992 /* Non excepting instruction. Clear the NE flag for the target 993 register. */ 994 SI NE_flags[2]; 995 GET_NE_FLAGS (NE_flags, H_SPR_GNER0); 996 CLEAR_NE_FLAG (NE_flags, target_index); 997 SET_NE_FLAGS (H_SPR_GNER0, NE_flags); 998 } 999 } 1000 } 1001 1002 /* Clear accumulators. */ 1003 void 1004 frvbf_clear_accumulators (SIM_CPU *current_cpu, SI acc_ix, int A) 1005 { 1006 SIM_DESC sd = CPU_STATE (current_cpu); 1007 int acc_mask = 1008 (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr500) ? 7 : 1009 (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) ? 7 : 1010 (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450) ? 11 : 1011 (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400) ? 3 : 1012 63; 1013 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu); 1014 1015 ps->mclracc_acc = acc_ix; 1016 ps->mclracc_A = A; 1017 if (A == 0 || acc_ix != 0) /* Clear 1 accumuator? */ 1018 { 1019 /* This instruction is a nop if the referenced accumulator is not 1020 implemented. */ 1021 if ((acc_ix & acc_mask) == acc_ix) 1022 sim_queue_fn_di_write (current_cpu, frvbf_h_acc40S_set, acc_ix, 0); 1023 } 1024 else 1025 { 1026 /* Clear all implemented accumulators. */ 1027 int i; 1028 for (i = 0; i <= acc_mask; ++i) 1029 if ((i & acc_mask) == i) 1030 sim_queue_fn_di_write (current_cpu, frvbf_h_acc40S_set, i, 0); 1031 } 1032 } 1033 1034 /* Functions to aid insn semantics. */ 1035 1036 /* Compute the result of the SCAN and SCANI insns after the shift and xor. */ 1037 SI 1038 frvbf_scan_result (SIM_CPU *current_cpu, SI value) 1039 { 1040 SI i; 1041 SI mask; 1042 1043 if (value == 0) 1044 return 63; 1045 1046 /* Find the position of the first non-zero bit. 1047 The loop will terminate since there is guaranteed to be at least one 1048 non-zero bit. */ 1049 mask = 1 << (sizeof (mask) * 8 - 1); 1050 for (i = 0; (value & mask) == 0; ++i) 1051 value <<= 1; 1052 1053 return i; 1054 } 1055 1056 /* Compute the result of the cut insns. */ 1057 SI 1058 frvbf_cut (SIM_CPU *current_cpu, SI reg1, SI reg2, SI cut_point) 1059 { 1060 SI result; 1061 cut_point &= 0x3f; 1062 if (cut_point < 32) 1063 { 1064 result = reg1 << cut_point; 1065 result |= (reg2 >> (32 - cut_point)) & ((1 << cut_point) - 1); 1066 } 1067 else 1068 result = reg2 << (cut_point - 32); 1069 1070 return result; 1071 } 1072 1073 /* Compute the result of the cut insns. */ 1074 SI 1075 frvbf_media_cut (SIM_CPU *current_cpu, DI acc, SI cut_point) 1076 { 1077 /* The cut point is the lower 6 bits (signed) of what we are passed. */ 1078 cut_point = cut_point << 26 >> 26; 1079 1080 /* The cut_point is relative to bit 40 of 64 bits. */ 1081 if (cut_point >= 0) 1082 return (acc << (cut_point + 24)) >> 32; 1083 1084 /* Extend the sign bit (bit 40) for negative cuts. */ 1085 if (cut_point == -32) 1086 return (acc << 24) >> 63; /* Special case for full shiftout. */ 1087 1088 return (acc << 24) >> (32 + -cut_point); 1089 } 1090 1091 /* Compute the result of the cut insns. */ 1092 SI 1093 frvbf_media_cut_ss (SIM_CPU *current_cpu, DI acc, SI cut_point) 1094 { 1095 /* The cut point is the lower 6 bits (signed) of what we are passed. */ 1096 cut_point = cut_point << 26 >> 26; 1097 1098 if (cut_point >= 0) 1099 { 1100 /* The cut_point is relative to bit 40 of 64 bits. */ 1101 DI shifted = acc << (cut_point + 24); 1102 DI unshifted = shifted >> (cut_point + 24); 1103 1104 /* The result will be saturated if significant bits are shifted out. */ 1105 if (unshifted != acc) 1106 { 1107 if (acc < 0) 1108 return 0x80000000; 1109 return 0x7fffffff; 1110 } 1111 } 1112 1113 /* The result will not be saturated, so use the code for the normal cut. */ 1114 return frvbf_media_cut (current_cpu, acc, cut_point); 1115 } 1116 1117 /* Compute the result of int accumulator cut (SCUTSS). */ 1118 SI 1119 frvbf_iacc_cut (SIM_CPU *current_cpu, DI acc, SI cut_point) 1120 { 1121 DI lower, upper; 1122 1123 /* The cut point is the lower 7 bits (signed) of what we are passed. */ 1124 cut_point = cut_point << 25 >> 25; 1125 1126 /* Conceptually, the operation is on a 128-bit sign-extension of ACC. 1127 The top bit of the return value corresponds to bit (63 - CUT_POINT) 1128 of this 128-bit value. 1129 1130 Since we can't deal with 128-bit values very easily, convert the 1131 operation into an equivalent 64-bit one. */ 1132 if (cut_point < 0) 1133 { 1134 /* Avoid an undefined shift operation. */ 1135 if (cut_point == -64) 1136 acc >>= 63; 1137 else 1138 acc >>= -cut_point; 1139 cut_point = 0; 1140 } 1141 1142 /* Get the shifted but unsaturated result. Set LOWER to the lowest 1143 32 bits of the result and UPPER to the result >> 31. */ 1144 if (cut_point < 32) 1145 { 1146 /* The cut loses the (32 - CUT_POINT) least significant bits. 1147 Round the result up if the most significant of these lost bits 1148 is 1. */ 1149 lower = acc >> (32 - cut_point); 1150 if (lower < 0x7fffffff) 1151 if (acc & LSBIT64 (32 - cut_point - 1)) 1152 lower++; 1153 upper = lower >> 31; 1154 } 1155 else 1156 { 1157 lower = acc << (cut_point - 32); 1158 upper = acc >> (63 - cut_point); 1159 } 1160 1161 /* Saturate the result. */ 1162 if (upper < -1) 1163 return ~0x7fffffff; 1164 else if (upper > 0) 1165 return 0x7fffffff; 1166 else 1167 return lower; 1168 } 1169 1170 /* Compute the result of shift-left-arithmetic-with-saturation (SLASS). */ 1171 SI 1172 frvbf_shift_left_arith_saturate (SIM_CPU *current_cpu, SI arg1, SI arg2) 1173 { 1174 int neg_arg1; 1175 1176 /* FIXME: what to do with negative shift amt? */ 1177 if (arg2 <= 0) 1178 return arg1; 1179 1180 if (arg1 == 0) 1181 return 0; 1182 1183 /* Signed shift by 31 or greater saturates by definition. */ 1184 if (arg2 >= 31) 1185 { 1186 if (arg1 > 0) 1187 return (SI) 0x7fffffff; 1188 else 1189 return (SI) 0x80000000; 1190 } 1191 1192 /* OK, arg2 is between 1 and 31. */ 1193 neg_arg1 = (arg1 < 0); 1194 do { 1195 arg1 <<= 1; 1196 /* Check for sign bit change (saturation). */ 1197 if (neg_arg1 && (arg1 >= 0)) 1198 return (SI) 0x80000000; 1199 else if (!neg_arg1 && (arg1 < 0)) 1200 return (SI) 0x7fffffff; 1201 } while (--arg2 > 0); 1202 1203 return arg1; 1204 } 1205 1206 /* Simulate the media custom insns. */ 1207 void 1208 frvbf_media_cop (SIM_CPU *current_cpu, int cop_num) 1209 { 1210 /* The semantics of the insn are a nop, since it is implementation defined. 1211 We do need to check whether it's implemented and set up for MTRAP 1212 if it's not. */ 1213 USI msr0 = GET_MSR (0); 1214 if (GET_MSR_EMCI (msr0) == 0) 1215 { 1216 /* no interrupt queued at this time. */ 1217 frv_set_mp_exception_registers (current_cpu, MTT_UNIMPLEMENTED_MPOP, 0); 1218 } 1219 } 1220 1221 /* Simulate the media average (MAVEH) insn. */ 1222 static HI 1223 do_media_average (SIM_CPU *current_cpu, HI arg1, HI arg2) 1224 { 1225 SIM_DESC sd = CPU_STATE (current_cpu); 1226 SI sum = (arg1 + arg2); 1227 HI result = sum >> 1; 1228 int rounding_value; 1229 1230 /* On fr4xx and fr550, check the rounding mode. On other machines 1231 rounding is always toward negative infinity and the result is 1232 already correctly rounded. */ 1233 switch (STATE_ARCHITECTURE (sd)->mach) 1234 { 1235 /* Need to check rounding mode. */ 1236 case bfd_mach_fr400: 1237 case bfd_mach_fr450: 1238 case bfd_mach_fr550: 1239 /* Check whether rounding will be required. Rounding will be required 1240 if the sum is an odd number. */ 1241 rounding_value = sum & 1; 1242 if (rounding_value) 1243 { 1244 USI msr0 = GET_MSR (0); 1245 /* Check MSR0.SRDAV to determine which bits control the rounding. */ 1246 if (GET_MSR_SRDAV (msr0)) 1247 { 1248 /* MSR0.RD controls rounding. */ 1249 switch (GET_MSR_RD (msr0)) 1250 { 1251 case 0: 1252 /* Round to nearest. */ 1253 if (result >= 0) 1254 ++result; 1255 break; 1256 case 1: 1257 /* Round toward 0. */ 1258 if (result < 0) 1259 ++result; 1260 break; 1261 case 2: 1262 /* Round toward positive infinity. */ 1263 ++result; 1264 break; 1265 case 3: 1266 /* Round toward negative infinity. The result is already 1267 correctly rounded. */ 1268 break; 1269 default: 1270 abort (); 1271 break; 1272 } 1273 } 1274 else 1275 { 1276 /* MSR0.RDAV controls rounding. If set, round toward positive 1277 infinity. Otherwise the result is already rounded correctly 1278 toward negative infinity. */ 1279 if (GET_MSR_RDAV (msr0)) 1280 ++result; 1281 } 1282 } 1283 break; 1284 default: 1285 break; 1286 } 1287 1288 return result; 1289 } 1290 1291 SI 1292 frvbf_media_average (SIM_CPU *current_cpu, SI reg1, SI reg2) 1293 { 1294 SI result; 1295 result = do_media_average (current_cpu, reg1 & 0xffff, reg2 & 0xffff); 1296 result &= 0xffff; 1297 result |= do_media_average (current_cpu, (reg1 >> 16) & 0xffff, 1298 (reg2 >> 16) & 0xffff) << 16; 1299 return result; 1300 } 1301 1302 /* Maintain a flag in order to know when to write the address of the next 1303 VLIW instruction into the LR register. Used by JMPL. JMPIL, and CALL. */ 1304 void 1305 frvbf_set_write_next_vliw_addr_to_LR (SIM_CPU *current_cpu, int value) 1306 { 1307 frvbf_write_next_vliw_addr_to_LR = value; 1308 } 1309 1310 void 1311 frvbf_set_ne_index (SIM_CPU *current_cpu, int index) 1312 { 1313 USI NE_flags[2]; 1314 1315 /* Save the target register so interrupt processing can set its NE flag 1316 in the event of an exception. */ 1317 frv_interrupt_state.ne_index = index; 1318 1319 /* Clear the NE flag of the target register. It will be reset if necessary 1320 in the event of an exception. */ 1321 GET_NE_FLAGS (NE_flags, H_SPR_FNER0); 1322 CLEAR_NE_FLAG (NE_flags, index); 1323 SET_NE_FLAGS (H_SPR_FNER0, NE_flags); 1324 } 1325 1326 void 1327 frvbf_force_update (SIM_CPU *current_cpu) 1328 { 1329 CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (current_cpu); 1330 int ix = CGEN_WRITE_QUEUE_INDEX (q); 1331 if (ix > 0) 1332 { 1333 CGEN_WRITE_QUEUE_ELEMENT *item = CGEN_WRITE_QUEUE_ELEMENT (q, ix - 1); 1334 item->flags |= FRV_WRITE_QUEUE_FORCE_WRITE; 1335 } 1336 } 1337 1338 /* Condition code logic. */ 1339 enum cr_ops { 1340 andcr, orcr, xorcr, nandcr, norcr, andncr, orncr, nandncr, norncr, 1341 num_cr_ops 1342 }; 1343 1344 enum cr_result {cr_undefined, cr_undefined1, cr_false, cr_true}; 1345 1346 static enum cr_result 1347 cr_logic[num_cr_ops][4][4] = { 1348 /* andcr */ 1349 { 1350 /* undefined undefined false true */ 1351 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1352 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1353 /* false */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1354 /* true */ {cr_undefined, cr_undefined, cr_false, cr_true } 1355 }, 1356 /* orcr */ 1357 { 1358 /* undefined undefined false true */ 1359 /* undefined */ {cr_undefined, cr_undefined, cr_false, cr_true }, 1360 /* undefined */ {cr_undefined, cr_undefined, cr_false, cr_true }, 1361 /* false */ {cr_false, cr_false, cr_false, cr_true }, 1362 /* true */ {cr_true, cr_true, cr_true, cr_true } 1363 }, 1364 /* xorcr */ 1365 { 1366 /* undefined undefined false true */ 1367 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1368 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1369 /* false */ {cr_undefined, cr_undefined, cr_false, cr_true }, 1370 /* true */ {cr_true, cr_true, cr_true, cr_false } 1371 }, 1372 /* nandcr */ 1373 { 1374 /* undefined undefined false true */ 1375 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1376 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1377 /* false */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1378 /* true */ {cr_undefined, cr_undefined, cr_true, cr_false } 1379 }, 1380 /* norcr */ 1381 { 1382 /* undefined undefined false true */ 1383 /* undefined */ {cr_undefined, cr_undefined, cr_true, cr_false }, 1384 /* undefined */ {cr_undefined, cr_undefined, cr_true, cr_false }, 1385 /* false */ {cr_true, cr_true, cr_true, cr_false }, 1386 /* true */ {cr_false, cr_false, cr_false, cr_false } 1387 }, 1388 /* andncr */ 1389 { 1390 /* undefined undefined false true */ 1391 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1392 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1393 /* false */ {cr_undefined, cr_undefined, cr_false, cr_true }, 1394 /* true */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined} 1395 }, 1396 /* orncr */ 1397 { 1398 /* undefined undefined false true */ 1399 /* undefined */ {cr_undefined, cr_undefined, cr_false, cr_true }, 1400 /* undefined */ {cr_undefined, cr_undefined, cr_false, cr_true }, 1401 /* false */ {cr_true, cr_true, cr_true, cr_true }, 1402 /* true */ {cr_false, cr_false, cr_false, cr_true } 1403 }, 1404 /* nandncr */ 1405 { 1406 /* undefined undefined false true */ 1407 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1408 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}, 1409 /* false */ {cr_undefined, cr_undefined, cr_true, cr_false }, 1410 /* true */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined} 1411 }, 1412 /* norncr */ 1413 { 1414 /* undefined undefined false true */ 1415 /* undefined */ {cr_undefined, cr_undefined, cr_true, cr_false }, 1416 /* undefined */ {cr_undefined, cr_undefined, cr_true, cr_false }, 1417 /* false */ {cr_false, cr_false, cr_false, cr_false }, 1418 /* true */ {cr_true, cr_true, cr_true, cr_false } 1419 } 1420 }; 1421 1422 UQI 1423 frvbf_cr_logic (SIM_CPU *current_cpu, SI operation, UQI arg1, UQI arg2) 1424 { 1425 return cr_logic[operation][arg1][arg2]; 1426 } 1427 1428 /* Cache Manipulation. */ 1429 void 1430 frvbf_insn_cache_preload (SIM_CPU *current_cpu, SI address, USI length, int lock) 1431 { 1432 /* If we need to count cycles, then the cache operation will be 1433 initiated from the model profiling functions. 1434 See frvbf_model_.... */ 1435 int hsr0 = GET_HSR0 (); 1436 if (GET_HSR0_ICE (hsr0)) 1437 { 1438 if (model_insn) 1439 { 1440 CPU_LOAD_ADDRESS (current_cpu) = address; 1441 CPU_LOAD_LENGTH (current_cpu) = length; 1442 CPU_LOAD_LOCK (current_cpu) = lock; 1443 } 1444 else 1445 { 1446 FRV_CACHE *cache = CPU_INSN_CACHE (current_cpu); 1447 frv_cache_preload (cache, address, length, lock); 1448 } 1449 } 1450 } 1451 1452 void 1453 frvbf_data_cache_preload (SIM_CPU *current_cpu, SI address, USI length, int lock) 1454 { 1455 /* If we need to count cycles, then the cache operation will be 1456 initiated from the model profiling functions. 1457 See frvbf_model_.... */ 1458 int hsr0 = GET_HSR0 (); 1459 if (GET_HSR0_DCE (hsr0)) 1460 { 1461 if (model_insn) 1462 { 1463 CPU_LOAD_ADDRESS (current_cpu) = address; 1464 CPU_LOAD_LENGTH (current_cpu) = length; 1465 CPU_LOAD_LOCK (current_cpu) = lock; 1466 } 1467 else 1468 { 1469 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); 1470 frv_cache_preload (cache, address, length, lock); 1471 } 1472 } 1473 } 1474 1475 void 1476 frvbf_insn_cache_unlock (SIM_CPU *current_cpu, SI address) 1477 { 1478 /* If we need to count cycles, then the cache operation will be 1479 initiated from the model profiling functions. 1480 See frvbf_model_.... */ 1481 int hsr0 = GET_HSR0 (); 1482 if (GET_HSR0_ICE (hsr0)) 1483 { 1484 if (model_insn) 1485 CPU_LOAD_ADDRESS (current_cpu) = address; 1486 else 1487 { 1488 FRV_CACHE *cache = CPU_INSN_CACHE (current_cpu); 1489 frv_cache_unlock (cache, address); 1490 } 1491 } 1492 } 1493 1494 void 1495 frvbf_data_cache_unlock (SIM_CPU *current_cpu, SI address) 1496 { 1497 /* If we need to count cycles, then the cache operation will be 1498 initiated from the model profiling functions. 1499 See frvbf_model_.... */ 1500 int hsr0 = GET_HSR0 (); 1501 if (GET_HSR0_DCE (hsr0)) 1502 { 1503 if (model_insn) 1504 CPU_LOAD_ADDRESS (current_cpu) = address; 1505 else 1506 { 1507 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); 1508 frv_cache_unlock (cache, address); 1509 } 1510 } 1511 } 1512 1513 void 1514 frvbf_insn_cache_invalidate (SIM_CPU *current_cpu, SI address, int all) 1515 { 1516 /* Make sure the insn was specified properly. -1 will be passed for ALL 1517 for a icei with A=0. */ 1518 if (all == -1) 1519 { 1520 frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION); 1521 return; 1522 } 1523 1524 /* If we need to count cycles, then the cache operation will be 1525 initiated from the model profiling functions. 1526 See frvbf_model_.... */ 1527 if (model_insn) 1528 { 1529 /* Record the all-entries flag for use in profiling. */ 1530 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu); 1531 ps->all_cache_entries = all; 1532 CPU_LOAD_ADDRESS (current_cpu) = address; 1533 } 1534 else 1535 { 1536 FRV_CACHE *cache = CPU_INSN_CACHE (current_cpu); 1537 if (all) 1538 frv_cache_invalidate_all (cache, 0/* flush? */); 1539 else 1540 frv_cache_invalidate (cache, address, 0/* flush? */); 1541 } 1542 } 1543 1544 void 1545 frvbf_data_cache_invalidate (SIM_CPU *current_cpu, SI address, int all) 1546 { 1547 /* Make sure the insn was specified properly. -1 will be passed for ALL 1548 for a dcei with A=0. */ 1549 if (all == -1) 1550 { 1551 frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION); 1552 return; 1553 } 1554 1555 /* If we need to count cycles, then the cache operation will be 1556 initiated from the model profiling functions. 1557 See frvbf_model_.... */ 1558 if (model_insn) 1559 { 1560 /* Record the all-entries flag for use in profiling. */ 1561 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu); 1562 ps->all_cache_entries = all; 1563 CPU_LOAD_ADDRESS (current_cpu) = address; 1564 } 1565 else 1566 { 1567 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); 1568 if (all) 1569 frv_cache_invalidate_all (cache, 0/* flush? */); 1570 else 1571 frv_cache_invalidate (cache, address, 0/* flush? */); 1572 } 1573 } 1574 1575 void 1576 frvbf_data_cache_flush (SIM_CPU *current_cpu, SI address, int all) 1577 { 1578 /* Make sure the insn was specified properly. -1 will be passed for ALL 1579 for a dcef with A=0. */ 1580 if (all == -1) 1581 { 1582 frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION); 1583 return; 1584 } 1585 1586 /* If we need to count cycles, then the cache operation will be 1587 initiated from the model profiling functions. 1588 See frvbf_model_.... */ 1589 if (model_insn) 1590 { 1591 /* Record the all-entries flag for use in profiling. */ 1592 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu); 1593 ps->all_cache_entries = all; 1594 CPU_LOAD_ADDRESS (current_cpu) = address; 1595 } 1596 else 1597 { 1598 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu); 1599 if (all) 1600 frv_cache_invalidate_all (cache, 1/* flush? */); 1601 else 1602 frv_cache_invalidate (cache, address, 1/* flush? */); 1603 } 1604 } 1605