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