1 1.1 christos /* CRIS v32 simulator support code 2 1.1.1.12 christos Copyright (C) 2004-2025 Free Software Foundation, Inc. 3 1.1 christos Contributed by Axis Communications. 4 1.1 christos 5 1.1 christos This file is part of the GNU simulators. 6 1.1 christos 7 1.1 christos This program is free software; you can redistribute it and/or modify 8 1.1 christos it under the terms of the GNU General Public License as published by 9 1.1 christos the Free Software Foundation; either version 3 of the License, or 10 1.1 christos (at your option) any later version. 11 1.1 christos 12 1.1 christos This program is distributed in the hope that it will be useful, 13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 1.1 christos GNU General Public License for more details. 16 1.1 christos 17 1.1 christos You should have received a copy of the GNU General Public License 18 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 1.1 christos 20 1.1 christos /* The infrastructure is based on that of i960.c. */ 21 1.1 christos 22 1.1.1.10 christos /* This must come before any other includes. */ 23 1.1.1.10 christos #include "defs.h" 24 1.1.1.10 christos 25 1.1 christos #define WANT_CPU_CRISV32F 26 1.1 christos 27 1.1 christos #define SPECIFIC_U_EXEC_FN 28 1.1 christos #define SPECIFIC_U_SKIP4_FN 29 1.1 christos #define SPECIFIC_U_CONST16_FN 30 1.1 christos #define SPECIFIC_U_CONST32_FN 31 1.1 christos #define SPECIFIC_U_MEM_FN 32 1.1 christos #define SPECIFIC_U_MOVEM_FN 33 1.1 christos #define BASENUM 32 34 1.1 christos #define CRIS_TLS_REGISTER 2 35 1.1 christos #include "cris-tmpl.c" 36 1.1 christos 37 1.1 christos #if WITH_PROFILE_MODEL_P 38 1.1 christos 39 1.1 christos /* Re-use the bit position for the BZ register, since there are no stall 40 1.1 christos cycles for reading or writing it. */ 41 1.1 christos #define CRIS_BZ_REGNO 16 42 1.1 christos #define CRIS_MODF_JUMP_MASK (1 << CRIS_BZ_REGNO) 43 1.1 christos /* Likewise for the WZ register, marking memory writes. */ 44 1.1 christos #define CRIS_WZ_REGNO 20 45 1.1 christos #define CRIS_MODF_MEM_WRITE_MASK (1 << CRIS_WZ_REGNO) 46 1.1 christos #define CRIS_MOF_REGNO (16 + 7) 47 1.1 christos #define CRIS_ALWAYS_CONDITION 14 48 1.1 christos 49 1.1 christos /* This macro must only be used in context where there's only one 50 1.1 christos dynamic cause for a penalty, except in the u-exec unit. */ 51 1.1 christos 52 1.1 christos #define PENALIZE1(CNT) \ 53 1.1 christos do \ 54 1.1 christos { \ 55 1.1 christos CPU_CRIS_MISC_PROFILE (current_cpu)->CNT++; \ 56 1.1 christos model_data->prev_prev_prev_modf_regs \ 57 1.1 christos = model_data->prev_prev_modf_regs; \ 58 1.1 christos model_data->prev_prev_modf_regs \ 59 1.1 christos = model_data->prev_modf_regs; \ 60 1.1 christos model_data->prev_modf_regs = 0; \ 61 1.1 christos model_data->prev_prev_prev_movem_dest_regs \ 62 1.1 christos = model_data->prev_prev_movem_dest_regs; \ 63 1.1 christos model_data->prev_prev_movem_dest_regs \ 64 1.1 christos = model_data->prev_movem_dest_regs; \ 65 1.1 christos model_data->prev_movem_dest_regs = 0; \ 66 1.1 christos } \ 67 1.1 christos while (0) 68 1.1 christos 69 1.1 christos 70 1.1 christos /* Model function for u-skip4 unit. */ 71 1.1 christos 72 1.1 christos int 73 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM, 74 1.1 christos _u_skip4)) (SIM_CPU *current_cpu, 75 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED, 76 1.1 christos int unit_num ATTRIBUTE_UNUSED, 77 1.1 christos int referenced ATTRIBUTE_UNUSED) 78 1.1 christos { 79 1.1 christos /* Handle PC not being updated with pbb. FIXME: What if not pbb? */ 80 1.1 christos CPU (h_pc) += 4; 81 1.1 christos return 0; 82 1.1 christos } 83 1.1 christos 84 1.1 christos /* Model function for u-exec unit. */ 85 1.1 christos 86 1.1 christos int 87 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM, 88 1.1 christos _u_exec)) (SIM_CPU *current_cpu, 89 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED, 90 1.1 christos int unit_num ATTRIBUTE_UNUSED, 91 1.1 christos int referenced ATTRIBUTE_UNUSED, 92 1.1 christos INT destreg_in, 93 1.1 christos INT srcreg, 94 1.1 christos INT destreg_out) 95 1.1 christos { 96 1.1 christos MODEL_CRISV32_DATA *model_data 97 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu); 98 1.1 christos UINT modf_regs 99 1.1 christos = ((destreg_out == -1 ? 0 : (1 << destreg_out)) 100 1.1 christos | model_data->modf_regs); 101 1.1 christos 102 1.1 christos if (srcreg != -1) 103 1.1 christos { 104 1.1 christos if (model_data->prev_movem_dest_regs & (1 << srcreg)) 105 1.1 christos { 106 1.1 christos PENALIZE1 (movemdst_stall_count); 107 1.1 christos PENALIZE1 (movemdst_stall_count); 108 1.1 christos PENALIZE1 (movemdst_stall_count); 109 1.1 christos } 110 1.1 christos else if (model_data->prev_prev_movem_dest_regs & (1 << srcreg)) 111 1.1 christos { 112 1.1 christos PENALIZE1 (movemdst_stall_count); 113 1.1 christos PENALIZE1 (movemdst_stall_count); 114 1.1 christos } 115 1.1 christos else if (model_data->prev_prev_prev_movem_dest_regs & (1 << srcreg)) 116 1.1 christos PENALIZE1 (movemdst_stall_count); 117 1.1 christos } 118 1.1 christos 119 1.1 christos if (destreg_in != -1) 120 1.1 christos { 121 1.1 christos if (model_data->prev_movem_dest_regs & (1 << destreg_in)) 122 1.1 christos { 123 1.1 christos PENALIZE1 (movemdst_stall_count); 124 1.1 christos PENALIZE1 (movemdst_stall_count); 125 1.1 christos PENALIZE1 (movemdst_stall_count); 126 1.1 christos } 127 1.1 christos else if (model_data->prev_prev_movem_dest_regs & (1 << destreg_in)) 128 1.1 christos { 129 1.1 christos PENALIZE1 (movemdst_stall_count); 130 1.1 christos PENALIZE1 (movemdst_stall_count); 131 1.1 christos } 132 1.1 christos else if (model_data->prev_prev_prev_movem_dest_regs & (1 << destreg_in)) 133 1.1 christos PENALIZE1 (movemdst_stall_count); 134 1.1 christos } 135 1.1 christos 136 1.1 christos model_data->prev_prev_prev_modf_regs 137 1.1 christos = model_data->prev_prev_modf_regs; 138 1.1 christos model_data->prev_prev_modf_regs = model_data->prev_modf_regs; 139 1.1 christos model_data->prev_modf_regs = modf_regs; 140 1.1 christos model_data->modf_regs = 0; 141 1.1 christos 142 1.1 christos model_data->prev_prev_prev_movem_dest_regs 143 1.1 christos = model_data->prev_prev_movem_dest_regs; 144 1.1 christos model_data->prev_prev_movem_dest_regs = model_data->prev_movem_dest_regs; 145 1.1 christos model_data->prev_movem_dest_regs = model_data->movem_dest_regs; 146 1.1 christos model_data->movem_dest_regs = 0; 147 1.1 christos 148 1.1 christos /* Handle PC not being updated with pbb. FIXME: What if not pbb? */ 149 1.1 christos CPU (h_pc) += 2; 150 1.1 christos return 1; 151 1.1 christos } 152 1.1 christos 153 1.1 christos /* Special case used when the destination is a special register. */ 154 1.1 christos 155 1.1 christos int 156 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM, 157 1.1 christos _u_exec_to_sr)) (SIM_CPU *current_cpu, 158 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED, 159 1.1 christos int unit_num ATTRIBUTE_UNUSED, 160 1.1 christos int referenced ATTRIBUTE_UNUSED, 161 1.1 christos INT srcreg, 162 1.1 christos INT specreg) 163 1.1 christos { 164 1.1 christos int specdest; 165 1.1 christos 166 1.1 christos if (specreg != -1) 167 1.1 christos specdest = specreg + 16; 168 1.1 christos else 169 1.1 christos abort (); 170 1.1 christos 171 1.1 christos return MY (XCONCAT3 (f_model_crisv,BASENUM,_u_exec)) 172 1.1 christos (current_cpu, NULL, 0, 0, -1, srcreg, 173 1.1 christos /* The positions for constant-zero registers BZ and WZ are recycled 174 1.1 christos for jump and memory-write markers. We must take precautions 175 1.1 christos here not to add false markers for them. It might be that the 176 1.1 christos hardware inserts stall cycles for instructions that actually try 177 1.1 christos and write those registers, but we'll burn that bridge when we 178 1.1 christos get to it; we'd have to find other free bits or make new 179 1.1 christos model_data variables. However, it's doubtful that there will 180 1.1 christos ever be a need to be cycle-correct for useless code, at least in 181 1.1 christos this particular simulator, mainly used for GCC testing. */ 182 1.1 christos specdest == CRIS_BZ_REGNO || specdest == CRIS_WZ_REGNO 183 1.1 christos ? -1 : specdest); 184 1.1 christos } 185 1.1 christos 186 1.1 christos 187 1.1 christos /* Special case for movem. */ 188 1.1 christos 189 1.1 christos int 190 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM, 191 1.1 christos _u_exec_movem)) (SIM_CPU *current_cpu, 192 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED, 193 1.1 christos int unit_num ATTRIBUTE_UNUSED, 194 1.1 christos int referenced ATTRIBUTE_UNUSED, 195 1.1 christos INT srcreg, 196 1.1 christos INT destreg_out) 197 1.1 christos { 198 1.1 christos return MY (XCONCAT3 (f_model_crisv,BASENUM,_u_exec)) 199 1.1 christos (current_cpu, NULL, 0, 0, -1, srcreg, destreg_out); 200 1.1 christos } 201 1.1 christos 202 1.1 christos /* Model function for u-const16 unit. */ 203 1.1 christos 204 1.1 christos int 205 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM, 206 1.1 christos _u_const16)) (SIM_CPU *current_cpu, 207 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED, 208 1.1 christos int unit_num ATTRIBUTE_UNUSED, 209 1.1 christos int referenced ATTRIBUTE_UNUSED) 210 1.1 christos { 211 1.1 christos MODEL_CRISV32_DATA *model_data 212 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu); 213 1.1 christos 214 1.1 christos /* If the previous insn was a jump of some sort and this insn 215 1.1 christos straddles a cache-line, there's a one-cycle penalty. 216 1.1 christos FIXME: Test-cases for normal const16 and others, like branch. */ 217 1.1 christos if ((model_data->prev_modf_regs & CRIS_MODF_JUMP_MASK) 218 1.1 christos && (CPU (h_pc) & 0x1e) == 0x1e) 219 1.1 christos PENALIZE1 (jumptarget_stall_count); 220 1.1 christos 221 1.1 christos /* Handle PC not being updated with pbb. FIXME: What if not pbb? */ 222 1.1 christos CPU (h_pc) += 2; 223 1.1 christos 224 1.1 christos return 0; 225 1.1 christos } 226 1.1 christos 227 1.1 christos /* Model function for u-const32 unit. */ 228 1.1 christos 229 1.1 christos int 230 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM, 231 1.1 christos _u_const32)) (SIM_CPU *current_cpu, 232 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED, 233 1.1 christos int unit_num ATTRIBUTE_UNUSED, 234 1.1 christos int referenced ATTRIBUTE_UNUSED) 235 1.1 christos { 236 1.1 christos MODEL_CRISV32_DATA *model_data 237 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu); 238 1.1 christos 239 1.1 christos /* If the previous insn was a jump of some sort and this insn 240 1.1 christos straddles a cache-line, there's a one-cycle penalty. */ 241 1.1 christos if ((model_data->prev_modf_regs & CRIS_MODF_JUMP_MASK) 242 1.1 christos && (CPU (h_pc) & 0x1e) == 0x1c) 243 1.1 christos PENALIZE1 (jumptarget_stall_count); 244 1.1 christos 245 1.1 christos /* Handle PC not being updated with pbb. FIXME: What if not pbb? */ 246 1.1 christos CPU (h_pc) += 4; 247 1.1 christos 248 1.1 christos return 0; 249 1.1 christos } 250 1.1 christos 251 1.1 christos /* Model function for u-mem unit. */ 252 1.1 christos 253 1.1 christos int 254 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM, 255 1.1 christos _u_mem)) (SIM_CPU *current_cpu, 256 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED, 257 1.1 christos int unit_num ATTRIBUTE_UNUSED, 258 1.1 christos int referenced ATTRIBUTE_UNUSED, 259 1.1 christos INT srcreg) 260 1.1 christos { 261 1.1 christos MODEL_CRISV32_DATA *model_data 262 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu); 263 1.1 christos 264 1.1 christos if (srcreg == -1) 265 1.1 christos abort (); 266 1.1 christos 267 1.1 christos /* If srcreg references a register modified in the previous cycle 268 1.1 christos through other than autoincrement, then there's a penalty: one 269 1.1 christos cycle. */ 270 1.1 christos if (model_data->prev_modf_regs & (1 << srcreg)) 271 1.1 christos PENALIZE1 (memsrc_stall_count); 272 1.1 christos 273 1.1 christos return 0; 274 1.1 christos } 275 1.1 christos 276 1.1 christos /* Model function for u-mem-r unit. */ 277 1.1 christos 278 1.1 christos int 279 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM, 280 1.1 christos _u_mem_r)) (SIM_CPU *current_cpu, 281 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED, 282 1.1 christos int unit_num ATTRIBUTE_UNUSED, 283 1.1 christos int referenced ATTRIBUTE_UNUSED) 284 1.1 christos { 285 1.1 christos MODEL_CRISV32_DATA *model_data 286 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu); 287 1.1 christos 288 1.1 christos /* There's a two-cycle penalty for read after a memory write in any of 289 1.1 christos the two previous cycles, known as a cache read-after-write hazard. 290 1.1 christos 291 1.1 christos This model function (the model_data member access) depends on being 292 1.1 christos executed before the u-exec unit. */ 293 1.1 christos if ((model_data->prev_modf_regs & CRIS_MODF_MEM_WRITE_MASK) 294 1.1 christos || (model_data->prev_prev_modf_regs & CRIS_MODF_MEM_WRITE_MASK)) 295 1.1 christos { 296 1.1 christos PENALIZE1 (memraw_stall_count); 297 1.1 christos PENALIZE1 (memraw_stall_count); 298 1.1 christos } 299 1.1 christos 300 1.1 christos return 0; 301 1.1 christos } 302 1.1 christos 303 1.1 christos /* Model function for u-mem-w unit. */ 304 1.1 christos 305 1.1 christos int 306 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM, 307 1.1 christos _u_mem_w)) (SIM_CPU *current_cpu, 308 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED, 309 1.1 christos int unit_num ATTRIBUTE_UNUSED, 310 1.1 christos int referenced ATTRIBUTE_UNUSED) 311 1.1 christos { 312 1.1 christos MODEL_CRISV32_DATA *model_data 313 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu); 314 1.1 christos 315 1.1 christos /* Mark that memory has been written. This model function (the 316 1.1 christos model_data member access) depends on being executed after the 317 1.1 christos u-exec unit. */ 318 1.1 christos model_data->prev_modf_regs |= CRIS_MODF_MEM_WRITE_MASK; 319 1.1 christos 320 1.1 christos return 0; 321 1.1 christos } 322 1.1 christos 323 1.1 christos /* Model function for u-movem-rtom unit. */ 324 1.1 christos 325 1.1 christos int 326 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM, 327 1.1 christos _u_movem_rtom)) (SIM_CPU *current_cpu, 328 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED, 329 1.1 christos int unit_num ATTRIBUTE_UNUSED, 330 1.1 christos int referenced ATTRIBUTE_UNUSED, 331 1.1 christos /* Deliberate order. */ 332 1.1 christos INT addrreg, INT limreg) 333 1.1 christos { 334 1.1 christos USI addr; 335 1.1 christos MODEL_CRISV32_DATA *model_data 336 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu); 337 1.1 christos 338 1.1 christos if (limreg == -1 || addrreg == -1) 339 1.1 christos abort (); 340 1.1 christos 341 1.1 christos addr = GET_H_GR (addrreg); 342 1.1 christos 343 1.1 christos /* The movem-to-memory instruction must not move a register modified 344 1.1 christos in one of the previous two cycles. Enforce by adding penalty 345 1.1 christos cycles. */ 346 1.1 christos if (model_data->prev_modf_regs & ((1 << (limreg + 1)) - 1)) 347 1.1 christos { 348 1.1 christos PENALIZE1 (movemsrc_stall_count); 349 1.1 christos PENALIZE1 (movemsrc_stall_count); 350 1.1 christos } 351 1.1 christos else if (model_data->prev_prev_modf_regs & ((1 << (limreg + 1)) - 1)) 352 1.1 christos PENALIZE1 (movemsrc_stall_count); 353 1.1 christos 354 1.1 christos /* One-cycle penalty for each cache-line straddled. Use the 355 1.1 christos documented expressions. Unfortunately no penalty cycles are 356 1.1 christos eliminated by any penalty cycles above. We file these numbers 357 1.1 christos separately, since they aren't schedulable for all cases. */ 358 1.1 christos if ((addr >> 5) == (((addr + 4 * (limreg + 1)) - 1) >> 5)) 359 1.1 christos ; 360 1.1 christos else if ((addr >> 5) == (((addr + 4 * (limreg + 1)) - 1) >> 5) - 1) 361 1.1 christos PENALIZE1 (movemaddr_stall_count); 362 1.1 christos else if ((addr >> 5) == (((addr + 4 * (limreg + 1)) - 1) >> 5) - 2) 363 1.1 christos { 364 1.1 christos PENALIZE1 (movemaddr_stall_count); 365 1.1 christos PENALIZE1 (movemaddr_stall_count); 366 1.1 christos } 367 1.1 christos else 368 1.1 christos abort (); 369 1.1 christos 370 1.1 christos return 0; 371 1.1 christos } 372 1.1 christos 373 1.1 christos /* Model function for u-movem-mtor unit. */ 374 1.1 christos 375 1.1 christos int 376 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM, 377 1.1 christos _u_movem_mtor)) (SIM_CPU *current_cpu, 378 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED, 379 1.1 christos int unit_num ATTRIBUTE_UNUSED, 380 1.1 christos int referenced ATTRIBUTE_UNUSED, 381 1.1 christos /* Deliberate order. */ 382 1.1 christos INT addrreg, INT limreg) 383 1.1 christos { 384 1.1 christos USI addr; 385 1.1 christos int nregs = limreg + 1; 386 1.1 christos MODEL_CRISV32_DATA *model_data 387 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu); 388 1.1 christos 389 1.1 christos if (limreg == -1 || addrreg == -1) 390 1.1 christos abort (); 391 1.1 christos 392 1.1 christos addr = GET_H_GR (addrreg); 393 1.1 christos 394 1.1 christos /* One-cycle penalty for each cache-line straddled. Use the 395 1.1 christos documented expressions. One cycle is the norm; more cycles are 396 1.1 christos counted as penalties. Unfortunately no penalty cycles here 397 1.1 christos eliminate penalty cycles indicated in ->movem_dest_regs. */ 398 1.1 christos if ((addr >> 5) == (((addr + 4 * nregs) - 1) >> 5) - 1) 399 1.1 christos PENALIZE1 (movemaddr_stall_count); 400 1.1 christos else if ((addr >> 5) == (((addr + 4 * nregs) - 1) >> 5) - 2) 401 1.1 christos { 402 1.1 christos PENALIZE1 (movemaddr_stall_count); 403 1.1 christos PENALIZE1 (movemaddr_stall_count); 404 1.1 christos } 405 1.1 christos 406 1.1 christos model_data->modf_regs |= ((1 << nregs) - 1); 407 1.1 christos model_data->movem_dest_regs |= ((1 << nregs) - 1); 408 1.1 christos return 0; 409 1.1 christos } 410 1.1 christos 411 1.1 christos 412 1.1 christos /* Model function for u-branch unit. 413 1.1 christos FIXME: newpc and cc are always wrong. */ 414 1.1 christos 415 1.1 christos int 416 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,_u_branch)) (SIM_CPU *current_cpu, 417 1.1 christos const IDESC *idesc, 418 1.1 christos int unit_num, int referenced) 419 1.1 christos { 420 1.1 christos CRIS_MISC_PROFILE *profp = CPU_CRIS_MISC_PROFILE (current_cpu); 421 1.1 christos USI pc = profp->old_pc; 422 1.1 christos MODEL_CRISV32_DATA *model_data 423 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu); 424 1.1 christos int taken = profp->branch_taken; 425 1.1 christos int branch_index = (pc & (N_CRISV32_BRANCH_PREDICTORS - 1)) >> 1; 426 1.1 christos int pred_taken = (profp->branch_predictors[branch_index] & 2) != 0; 427 1.1 christos 428 1.1 christos if (taken != pred_taken) 429 1.1 christos { 430 1.1 christos PENALIZE1 (branch_stall_count); 431 1.1 christos PENALIZE1 (branch_stall_count); 432 1.1 christos } 433 1.1 christos 434 1.1 christos if (taken) 435 1.1 christos { 436 1.1 christos if (profp->branch_predictors[branch_index] < 3) 437 1.1 christos profp->branch_predictors[branch_index]++; 438 1.1 christos 439 1.1 christos return MY (XCONCAT3 (f_model_crisv,BASENUM,_u_jump)) 440 1.1 christos (current_cpu, idesc, unit_num, referenced, -1); 441 1.1 christos } 442 1.1 christos 443 1.1 christos if (profp->branch_predictors[branch_index] != 0) 444 1.1 christos profp->branch_predictors[branch_index]--; 445 1.1 christos 446 1.1 christos return 0; 447 1.1 christos } 448 1.1 christos 449 1.1 christos /* Model function for u-jump-r unit. */ 450 1.1 christos 451 1.1 christos int 452 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM, 453 1.1 christos _u_jump_r)) (SIM_CPU *current_cpu, 454 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED, 455 1.1 christos int unit_num ATTRIBUTE_UNUSED, 456 1.1 christos int referenced ATTRIBUTE_UNUSED, 457 1.1 christos int regno) 458 1.1 christos { 459 1.1 christos MODEL_CRISV32_DATA *model_data 460 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu); 461 1.1 christos 462 1.1 christos if (regno == -1) 463 1.1 christos abort (); 464 1.1 christos 465 1.1 christos /* For jump-to-register, the register must not have been modified the 466 1.1 christos last two cycles. Penalty: two cycles from the modifying insn. */ 467 1.1 christos if ((1 << regno) & model_data->prev_modf_regs) 468 1.1 christos { 469 1.1 christos PENALIZE1 (jumpsrc_stall_count); 470 1.1 christos PENALIZE1 (jumpsrc_stall_count); 471 1.1 christos } 472 1.1 christos else if ((1 << regno) & model_data->prev_prev_modf_regs) 473 1.1 christos PENALIZE1 (jumpsrc_stall_count); 474 1.1 christos 475 1.1 christos return 0; 476 1.1 christos } 477 1.1 christos 478 1.1 christos /* Model function for u-jump-sr unit. */ 479 1.1 christos 480 1.1 christos int 481 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,_u_jump_sr)) (SIM_CPU *current_cpu, 482 1.1 christos const IDESC *idesc, 483 1.1 christos int unit_num, int referenced, 484 1.1 christos int sr_regno) 485 1.1 christos { 486 1.1 christos int regno; 487 1.1 christos 488 1.1 christos MODEL_CRISV32_DATA *model_data 489 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu); 490 1.1 christos 491 1.1 christos if (sr_regno == -1) 492 1.1 christos abort (); 493 1.1 christos 494 1.1 christos regno = sr_regno + 16; 495 1.1 christos 496 1.1 christos /* For jump-to-register, the register must not have been modified the 497 1.1 christos last two cycles. Penalty: two cycles from the modifying insn. */ 498 1.1 christos if ((1 << regno) & model_data->prev_modf_regs) 499 1.1 christos { 500 1.1 christos PENALIZE1 (jumpsrc_stall_count); 501 1.1 christos PENALIZE1 (jumpsrc_stall_count); 502 1.1 christos } 503 1.1 christos else if ((1 << regno) & model_data->prev_prev_modf_regs) 504 1.1 christos PENALIZE1 (jumpsrc_stall_count); 505 1.1 christos 506 1.1 christos return 507 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,_u_jump)) (current_cpu, idesc, 508 1.1 christos unit_num, referenced, -1); 509 1.1 christos } 510 1.1 christos 511 1.1 christos /* Model function for u-jump unit. */ 512 1.1 christos 513 1.1 christos int 514 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM, 515 1.1 christos _u_jump)) (SIM_CPU *current_cpu, 516 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED, 517 1.1 christos int unit_num ATTRIBUTE_UNUSED, 518 1.1 christos int referenced ATTRIBUTE_UNUSED, 519 1.1 christos int out_sr_regno) 520 1.1 christos { 521 1.1 christos MODEL_CRISV32_DATA *model_data 522 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu); 523 1.1 christos 524 1.1 christos /* Mark that we made a jump. */ 525 1.1 christos model_data->modf_regs 526 1.1 christos |= (CRIS_MODF_JUMP_MASK 527 1.1 christos | (out_sr_regno == -1 || out_sr_regno == CRIS_BZ_REGNO 528 1.1 christos ? 0 : (1 << (out_sr_regno + 16)))); 529 1.1 christos return 0; 530 1.1 christos } 531 1.1 christos 532 1.1 christos /* Model function for u-multiply unit. */ 533 1.1 christos 534 1.1 christos int 535 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM, 536 1.1 christos _u_multiply)) (SIM_CPU *current_cpu, 537 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED, 538 1.1 christos int unit_num ATTRIBUTE_UNUSED, 539 1.1 christos int referenced ATTRIBUTE_UNUSED, 540 1.1 christos int srcreg, int destreg) 541 1.1 christos { 542 1.1 christos MODEL_CRISV32_DATA *model_data 543 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu); 544 1.1 christos 545 1.1 christos /* Sanity-check for cases that should never happen. */ 546 1.1 christos if (srcreg == -1 || destreg == -1) 547 1.1 christos abort (); 548 1.1 christos 549 1.1 christos /* This takes extra cycles when one of the inputs has been modified 550 1.1 christos through other than autoincrement in the previous cycle. Penalty: 551 1.1 christos one cycle. */ 552 1.1 christos if (((1 << srcreg) | (1 << destreg)) & model_data->prev_modf_regs) 553 1.1 christos PENALIZE1 (mulsrc_stall_count); 554 1.1 christos 555 1.1 christos /* We modified the multiplication destination (marked in u-exec) and 556 1.1 christos the MOF register. */ 557 1.1 christos model_data->modf_regs |= (1 << CRIS_MOF_REGNO); 558 1.1 christos return 0; 559 1.1 christos } 560 1.1 christos 561 1.1 christos #endif /* WITH_PROFILE_MODEL_P */ 562 1.1 christos 563 1.1 christos int 564 1.1 christos MY (deliver_interrupt) (SIM_CPU *current_cpu, 565 1.1 christos enum cris_interrupt_type type, 566 1.1 christos unsigned int vec) 567 1.1 christos { 568 1.1.1.10 christos uint32_t old_ccs, shifted_ccs, new_ccs; 569 1.1 christos unsigned char entryaddr_le[4]; 570 1.1 christos int was_user; 571 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 572 1.1.1.10 christos uint32_t entryaddr; 573 1.1 christos 574 1.1 christos /* We haven't implemented other interrupt-types yet. */ 575 1.1 christos if (type != CRIS_INT_INT) 576 1.1 christos abort (); 577 1.1 christos 578 1.1 christos /* We're called outside of branch delay slots etc, so we don't check 579 1.1 christos for that. */ 580 1.1 christos if (!GET_H_IBIT_V32 ()) 581 1.1 christos return 0; 582 1.1 christos 583 1.1 christos old_ccs = GET_H_SR_V32 (H_SR_CCS); 584 1.1 christos shifted_ccs = (old_ccs << 10) & ((1 << 30) - 1); 585 1.1 christos 586 1.1 christos /* The M bit is handled by code below and the M bit setter function, but 587 1.1 christos we need to preserve the Q bit. */ 588 1.1.1.10 christos new_ccs = shifted_ccs | (old_ccs & (uint32_t) 0x80000000UL); 589 1.1 christos was_user = GET_H_UBIT_V32 (); 590 1.1 christos 591 1.1 christos /* We need to force kernel mode since the setter method doesn't allow 592 1.1 christos it. Then we can use setter methods at will, since they then 593 1.1 christos recognize that we're in kernel mode. */ 594 1.1 christos CPU (h_ubit_v32) = 0; 595 1.1 christos 596 1.1 christos SET_H_SR (H_SR_CCS, new_ccs); 597 1.1 christos 598 1.1 christos if (was_user) 599 1.1 christos { 600 1.1 christos /* These methods require that user mode is unset. */ 601 1.1 christos SET_H_SR (H_SR_USP, GET_H_GR (H_GR_SP)); 602 1.1 christos SET_H_GR (H_GR_SP, GET_H_KERNEL_SP ()); 603 1.1 christos } 604 1.1 christos 605 1.1 christos /* ERP setting is simplified by not taking interrupts in delay-slots 606 1.1 christos or when halting. */ 607 1.1 christos /* For all other exceptions than guru and NMI, store the return 608 1.1 christos address in ERP and set EXS and EXD here. */ 609 1.1 christos SET_H_SR (H_SR_ERP, GET_H_PC ()); 610 1.1 christos 611 1.1 christos /* Simplified by not having exception types (fault indications). */ 612 1.1 christos SET_H_SR_V32 (H_SR_EXS, (vec * 256)); 613 1.1 christos SET_H_SR_V32 (H_SR_EDA, 0); 614 1.1 christos 615 1.1 christos if (sim_core_read_buffer (sd, 616 1.1 christos current_cpu, 617 1.1 christos read_map, entryaddr_le, 618 1.1 christos GET_H_SR (H_SR_EBP) + vec * 4, 4) == 0) 619 1.1 christos { 620 1.1 christos /* Nothing to do actually; either abort or send a signal. */ 621 1.1.1.5 christos sim_core_signal (sd, current_cpu, CPU_PC_GET (current_cpu), 0, 4, 622 1.1 christos GET_H_SR (H_SR_EBP) + vec * 4, 623 1.1 christos read_transfer, sim_core_unmapped_signal); 624 1.1 christos return 0; 625 1.1 christos } 626 1.1 christos 627 1.1 christos entryaddr = bfd_getl32 (entryaddr_le); 628 1.1 christos SET_H_PC (entryaddr); 629 1.1 christos 630 1.1 christos return 1; 631 1.1 christos } 632