1 /* CRIS base simulator support code 2 Copyright (C) 2004-2015 Free Software Foundation, Inc. 3 Contributed by Axis Communications. 4 5 This file is part of the GNU simulators. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 /* The infrastructure is based on that of i960.c. */ 21 22 #define WANT_CPU 23 24 #include "sim-main.h" 25 #include "cgen-mem.h" 26 #include "cgen-ops.h" 27 28 #define MY(f) XCONCAT3(crisv,BASENUM,f) 29 30 /* Dispatcher for break insn. */ 31 32 USI 33 MY (f_break_handler) (SIM_CPU *cpu, USI breaknum, USI pc) 34 { 35 SIM_DESC sd = CPU_STATE (cpu); 36 USI ret = pc + 2; 37 38 MY (f_h_pc_set) (cpu, ret); 39 40 /* FIXME: Error out if IBR or ERP set. */ 41 switch (breaknum) 42 { 43 case 13: 44 MY (f_h_gr_set (cpu, 10, 45 cris_break_13_handler (cpu, 46 MY (f_h_gr_get (cpu, 9)), 47 MY (f_h_gr_get (cpu, 10)), 48 MY (f_h_gr_get (cpu, 11)), 49 MY (f_h_gr_get (cpu, 12)), 50 MY (f_h_gr_get (cpu, 13)), 51 MY (f_h_sr_get (cpu, 7)), 52 MY (f_h_sr_get (cpu, 11)), 53 pc))); 54 break; 55 56 case 14: 57 sim_io_printf (sd, "%x\n", MY (f_h_gr_get (cpu, 3))); 58 break; 59 60 case 15: 61 /* Re-use the Linux exit call. */ 62 cris_break_13_handler (cpu, /* TARGET_SYS_exit */ 1, 0, 63 0, 0, 0, 0, 0, pc); 64 65 default: 66 abort (); 67 } 68 69 return MY (f_h_pc_get) (cpu); 70 } 71 72 /* Accessor function for simulator internal use. 73 Note the contents of BUF are in target byte order. */ 74 75 int 76 MY (f_fetch_register) (SIM_CPU *current_cpu, int rn, 77 unsigned char *buf, int len ATTRIBUTE_UNUSED) 78 { 79 SETTSI (buf, XCONCAT3(crisv,BASENUM,f_h_gr_get) (current_cpu, rn)); 80 return -1; 81 } 82 83 /* Accessor function for simulator internal use. 84 Note the contents of BUF are in target byte order. */ 85 86 int 87 MY (f_store_register) (SIM_CPU *current_cpu, int rn, 88 unsigned char *buf, int len ATTRIBUTE_UNUSED) 89 { 90 XCONCAT3(crisv,BASENUM,f_h_gr_set) (current_cpu, rn, GETTSI (buf)); 91 return -1; 92 } 93 94 #if WITH_PROFILE_MODEL_P 95 96 /* FIXME: Some of these should be inline or macros. Later. */ 97 98 /* Initialize cycle counting for an insn. 99 FIRST_P is non-zero if this is the first insn in a set of parallel 100 insns. */ 101 102 void 103 MY (f_model_insn_before) (SIM_CPU *current_cpu, int first_p ATTRIBUTE_UNUSED) 104 { 105 /* To give the impression that we actually know what PC is, we have to 106 dump register contents *before* the *next* insn, not after the 107 *previous* insn. Uhh... */ 108 109 /* FIXME: Move this to separate, overridable function. */ 110 if ((CPU_CRIS_MISC_PROFILE (current_cpu)->flags 111 & FLAG_CRIS_MISC_PROFILE_XSIM_TRACE) 112 #ifdef GET_H_INSN_PREFIXED_P 113 /* For versions with prefixed insns, trace the combination as 114 one insn. */ 115 && !GET_H_INSN_PREFIXED_P () 116 #endif 117 && 1) 118 { 119 int i; 120 char flags[7]; 121 unsigned64 cycle_count; 122 123 SIM_DESC sd = CPU_STATE (current_cpu); 124 125 cris_trace_printf (sd, current_cpu, "%lx ", 126 0xffffffffUL & (unsigned long) (CPU (h_pc))); 127 128 for (i = 0; i < 15; i++) 129 cris_trace_printf (sd, current_cpu, "%lx ", 130 0xffffffffUL 131 & (unsigned long) (XCONCAT3(crisv,BASENUM, 132 f_h_gr_get) (current_cpu, 133 i))); 134 flags[0] = GET_H_IBIT () != 0 ? 'I' : 'i'; 135 flags[1] = GET_H_XBIT () != 0 ? 'X' : 'x'; 136 flags[2] = GET_H_NBIT () != 0 ? 'N' : 'n'; 137 flags[3] = GET_H_ZBIT () != 0 ? 'Z' : 'z'; 138 flags[4] = GET_H_VBIT () != 0 ? 'V' : 'v'; 139 flags[5] = GET_H_CBIT () != 0 ? 'C' : 'c'; 140 flags[6] = 0; 141 142 /* For anything else than basic tracing we'd add stall cycles for 143 e.g. unaligned accesses. FIXME: add --cris-trace=x options to 144 match --cris-cycles=x. */ 145 cycle_count 146 = (CPU_CRIS_MISC_PROFILE (current_cpu)->basic_cycle_count 147 - CPU_CRIS_PREV_MISC_PROFILE (current_cpu)->basic_cycle_count); 148 149 /* Emit ACR after flags and cycle count for this insn. */ 150 if (BASENUM == 32) 151 cris_trace_printf (sd, current_cpu, "%s %d %lx\n", flags, 152 (int) cycle_count, 153 0xffffffffUL 154 & (unsigned long) (XCONCAT3(crisv,BASENUM, 155 f_h_gr_get) (current_cpu, 156 15))); 157 else 158 cris_trace_printf (sd, current_cpu, "%s %d\n", flags, 159 (int) cycle_count); 160 161 CPU_CRIS_PREV_MISC_PROFILE (current_cpu)[0] 162 = CPU_CRIS_MISC_PROFILE (current_cpu)[0]; 163 } 164 } 165 166 /* Record the cycles computed for an insn. 167 LAST_P is non-zero if this is the last insn in a set of parallel insns, 168 and we update the total cycle count. 169 CYCLES is the cycle count of the insn. */ 170 171 void 172 MY (f_model_insn_after) (SIM_CPU *current_cpu, int last_p ATTRIBUTE_UNUSED, 173 int cycles) 174 { 175 PROFILE_DATA *p = CPU_PROFILE_DATA (current_cpu); 176 177 PROFILE_MODEL_TOTAL_CYCLES (p) += cycles; 178 CPU_CRIS_MISC_PROFILE (current_cpu)->basic_cycle_count += cycles; 179 PROFILE_MODEL_CUR_INSN_CYCLES (p) = cycles; 180 181 #if WITH_HW 182 /* For some reason, we don't get to the sim_events_tick call in 183 cgen-run.c:engine_run_1. Besides, more than one cycle has 184 passed, so we want sim_events_tickn anyway. The "events we want 185 to process" is usually to initiate an interrupt, but might also 186 be other events. We can't do the former until the main loop is 187 at point where it accepts changing the PC without internal 188 inconsistency, so just set a flag and wait. */ 189 if (sim_events_tickn (CPU_STATE (current_cpu), cycles)) 190 STATE_EVENTS (CPU_STATE (current_cpu))->work_pending = 1; 191 #endif 192 } 193 194 /* Initialize cycle counting for an insn. 195 FIRST_P is non-zero if this is the first insn in a set of parallel 196 insns. */ 197 198 void 199 MY (f_model_init_insn_cycles) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED, 200 int first_p ATTRIBUTE_UNUSED) 201 { 202 abort (); 203 } 204 205 /* Record the cycles computed for an insn. 206 LAST_P is non-zero if this is the last insn in a set of parallel insns, 207 and we update the total cycle count. */ 208 209 void 210 MY (f_model_update_insn_cycles) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED, 211 int last_p ATTRIBUTE_UNUSED) 212 { 213 abort (); 214 } 215 216 #if 0 217 void 218 MY (f_model_record_cycles) (SIM_CPU *current_cpu, unsigned long cycles) 219 { 220 abort (); 221 } 222 223 void 224 MY (f_model_mark_get_h_gr) (SIM_CPU *current_cpu, ARGBUF *abuf) 225 { 226 abort (); 227 } 228 229 void 230 MY (f_model_mark_set_h_gr) (SIM_CPU *current_cpu, ARGBUF *abuf) 231 { 232 abort (); 233 } 234 #endif 235 236 /* Set the thread register contents. */ 237 238 void 239 MY (set_target_thread_data) (SIM_CPU *current_cpu, USI val) 240 { 241 (CPU (XCONCAT2 (h_sr_v, BASENUM) [CRIS_TLS_REGISTER])) = val; 242 } 243 244 /* Create the context for a thread. */ 245 246 void * 247 MY (make_thread_cpu_data) (SIM_CPU *current_cpu, void *context) 248 { 249 void *info = xmalloc (current_cpu->thread_cpu_data_size); 250 251 if (context != NULL) 252 memcpy (info, 253 context, 254 current_cpu->thread_cpu_data_size); 255 else 256 memset (info, 0, current_cpu->thread_cpu_data_size),abort(); 257 return info; 258 } 259 260 /* Hook function for per-cpu simulator initialization. */ 261 262 void 263 MY (f_specific_init) (SIM_CPU *current_cpu) 264 { 265 current_cpu->make_thread_cpu_data = MY (make_thread_cpu_data); 266 current_cpu->thread_cpu_data_size = sizeof (current_cpu->cpu_data); 267 current_cpu->set_target_thread_data = MY (set_target_thread_data); 268 #if WITH_HW 269 current_cpu->deliver_interrupt = MY (deliver_interrupt); 270 #endif 271 } 272 273 /* Model function for arbitrary single stall cycles. */ 274 275 int 276 MY (XCONCAT3 (f_model_crisv,BASENUM, 277 _u_stall)) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED, 278 const IDESC *idesc, 279 int unit_num, 280 int referenced ATTRIBUTE_UNUSED) 281 { 282 return idesc->timing->units[unit_num].done; 283 } 284 285 #ifndef SPECIFIC_U_SKIP4_FN 286 287 /* Model function for u-skip4 unit. */ 288 289 int 290 MY (XCONCAT3 (f_model_crisv,BASENUM, 291 _u_skip4)) (SIM_CPU *current_cpu, 292 const IDESC *idesc, 293 int unit_num, 294 int referenced ATTRIBUTE_UNUSED) 295 { 296 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */ 297 CPU (h_pc) += 4; 298 return idesc->timing->units[unit_num].done; 299 } 300 301 #endif 302 303 #ifndef SPECIFIC_U_EXEC_FN 304 305 /* Model function for u-exec unit. */ 306 307 int 308 MY (XCONCAT3 (f_model_crisv,BASENUM, 309 _u_exec)) (SIM_CPU *current_cpu, 310 const IDESC *idesc, 311 int unit_num, int referenced ATTRIBUTE_UNUSED) 312 { 313 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */ 314 CPU (h_pc) += 2; 315 return idesc->timing->units[unit_num].done; 316 } 317 #endif 318 319 #ifndef SPECIFIC_U_MEM_FN 320 321 /* Model function for u-mem unit. */ 322 323 int 324 MY (XCONCAT3 (f_model_crisv,BASENUM, 325 _u_mem)) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED, 326 const IDESC *idesc, 327 int unit_num, 328 int referenced ATTRIBUTE_UNUSED) 329 { 330 return idesc->timing->units[unit_num].done; 331 } 332 #endif 333 334 #ifndef SPECIFIC_U_CONST16_FN 335 336 /* Model function for u-const16 unit. */ 337 338 int 339 MY (XCONCAT3 (f_model_crisv,BASENUM, 340 _u_const16)) (SIM_CPU *current_cpu, 341 const IDESC *idesc, 342 int unit_num, 343 int referenced ATTRIBUTE_UNUSED) 344 { 345 CPU (h_pc) += 2; 346 return idesc->timing->units[unit_num].done; 347 } 348 #endif /* SPECIFIC_U_CONST16_FN */ 349 350 #ifndef SPECIFIC_U_CONST32_FN 351 352 /* This will be incorrect for early models, where a dword always take 353 two cycles. */ 354 #define CRIS_MODEL_MASK_PC_STALL 2 355 356 /* Model function for u-const32 unit. */ 357 358 int 359 MY (XCONCAT3 (f_model_crisv,BASENUM, 360 _u_const32)) (SIM_CPU *current_cpu, 361 const IDESC *idesc, 362 int unit_num, 363 int referenced ATTRIBUTE_UNUSED) 364 { 365 int unaligned_extra 366 = (((CPU (h_pc) + 2) & CRIS_MODEL_MASK_PC_STALL) 367 == CRIS_MODEL_MASK_PC_STALL); 368 369 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */ 370 CPU_CRIS_MISC_PROFILE (current_cpu)->unaligned_mem_dword_count 371 += unaligned_extra; 372 373 CPU (h_pc) += 4; 374 return idesc->timing->units[unit_num].done; 375 } 376 #endif /* SPECIFIC_U_CONST32_FN */ 377 378 #ifndef SPECIFIC_U_MOVEM_FN 379 380 /* Model function for u-movem unit. */ 381 382 int 383 MY (XCONCAT3 (f_model_crisv,BASENUM, 384 _u_movem)) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED, 385 const IDESC *idesc ATTRIBUTE_UNUSED, 386 int unit_num ATTRIBUTE_UNUSED, 387 int referenced ATTRIBUTE_UNUSED, 388 INT limreg) 389 { 390 /* FIXME: Add cycles for misalignment. */ 391 392 if (limreg == -1) 393 abort (); 394 395 /* We don't record movem move cycles in movemsrc_stall_count since 396 those cycles have historically been handled as ordinary cycles. */ 397 return limreg + 1; 398 } 399 #endif /* SPECIFIC_U_MOVEM_FN */ 400 401 #endif /* WITH_PROFILE_MODEL_P */ 402