1 /* CRIS base simulator support code
2 Copyright (C) 2004-2024 Free Software Foundation, Inc.
3 Contributed by Axis Communications.
5 This file is part of the GNU simulators.
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.
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.
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/>. */
20 /* The infrastructure is based on that of i960.c. */
22 /* This must come before any other includes. */
33 #define MY(f) XCONCAT3(crisv,BASENUM,f)
35 /* Dispatcher for break insn. */
38 MY (f_break_handler
) (SIM_CPU
*cpu
, USI breaknum
, USI pc
)
40 SIM_DESC sd
= CPU_STATE (cpu
);
43 MY (f_h_pc_set
) (cpu
, ret
);
45 /* FIXME: Error out if IBR or ERP set. */
49 MY (f_h_gr_set (cpu
, 10,
50 cris_break_13_handler (cpu
,
51 MY (f_h_gr_get (cpu
, 9)),
52 MY (f_h_gr_get (cpu
, 10)),
53 MY (f_h_gr_get (cpu
, 11)),
54 MY (f_h_gr_get (cpu
, 12)),
55 MY (f_h_gr_get (cpu
, 13)),
56 MY (f_h_sr_get (cpu
, 7)),
57 MY (f_h_sr_get (cpu
, 11)),
62 sim_io_printf (sd
, "%x\n", MY (f_h_gr_get (cpu
, 3)));
66 /* Re-use the Linux exit call. */
67 cris_break_13_handler (cpu
, /* TARGET_SYS_exit */ 1, 0,
70 /* This shouldn't be reached, but we can't mark break 13 as noreturn
71 since there are some calls which should return. */
72 ATTRIBUTE_FALLTHROUGH
;
78 return MY (f_h_pc_get
) (cpu
);
81 /* Accessor function for simulator internal use.
82 Note the contents of BUF are in target byte order. */
85 MY (f_fetch_register
) (SIM_CPU
*current_cpu
, int rn
, void *buf
,
86 int len ATTRIBUTE_UNUSED
)
88 SETTSI (buf
, XCONCAT3(crisv
,BASENUM
,f_h_gr_get
) (current_cpu
, rn
));
92 /* Accessor function for simulator internal use.
93 Note the contents of BUF are in target byte order. */
96 MY (f_store_register
) (SIM_CPU
*current_cpu
, int rn
, const void *buf
,
97 int len ATTRIBUTE_UNUSED
)
99 XCONCAT3(crisv
,BASENUM
,f_h_gr_set
) (current_cpu
, rn
, GETTSI (buf
));
103 #if WITH_PROFILE_MODEL_P
105 /* FIXME: Some of these should be inline or macros. Later. */
107 /* Initialize cycle counting for an insn.
108 FIRST_P is non-zero if this is the first insn in a set of parallel
112 MY (f_model_insn_before
) (SIM_CPU
*current_cpu
, int first_p ATTRIBUTE_UNUSED
)
114 /* To give the impression that we actually know what PC is, we have to
115 dump register contents *before* the *next* insn, not after the
116 *previous* insn. Uhh... */
118 /* FIXME: Move this to separate, overridable function. */
119 if ((CPU_CRIS_MISC_PROFILE (current_cpu
)->flags
120 & FLAG_CRIS_MISC_PROFILE_XSIM_TRACE
)
121 #ifdef GET_H_INSN_PREFIXED_P
122 /* For versions with prefixed insns, trace the combination as
124 && !GET_H_INSN_PREFIXED_P ()
130 uint64_t cycle_count
;
132 SIM_DESC sd
= CPU_STATE (current_cpu
);
134 cris_trace_printf (sd
, current_cpu
, "%lx ",
135 0xffffffffUL
& (unsigned long) (CPU (h_pc
)));
137 for (i
= 0; i
< 15; i
++)
138 cris_trace_printf (sd
, current_cpu
, "%lx ",
140 & (unsigned long) (XCONCAT3(crisv
,BASENUM
,
141 f_h_gr_get
) (current_cpu
,
143 flags
[0] = GET_H_IBIT () != 0 ? 'I' : 'i';
144 flags
[1] = GET_H_XBIT () != 0 ? 'X' : 'x';
145 flags
[2] = GET_H_NBIT () != 0 ? 'N' : 'n';
146 flags
[3] = GET_H_ZBIT () != 0 ? 'Z' : 'z';
147 flags
[4] = GET_H_VBIT () != 0 ? 'V' : 'v';
148 flags
[5] = GET_H_CBIT () != 0 ? 'C' : 'c';
151 /* For anything else than basic tracing we'd add stall cycles for
152 e.g. unaligned accesses. FIXME: add --cris-trace=x options to
153 match --cris-cycles=x. */
155 = (CPU_CRIS_MISC_PROFILE (current_cpu
)->basic_cycle_count
156 - CPU_CRIS_PREV_MISC_PROFILE (current_cpu
)->basic_cycle_count
);
158 /* Emit ACR after flags and cycle count for this insn. */
160 cris_trace_printf (sd
, current_cpu
, "%s %d %lx\n", flags
,
163 & (unsigned long) (XCONCAT3(crisv
,BASENUM
,
164 f_h_gr_get
) (current_cpu
,
167 cris_trace_printf (sd
, current_cpu
, "%s %d\n", flags
,
170 CPU_CRIS_PREV_MISC_PROFILE (current_cpu
)[0]
171 = CPU_CRIS_MISC_PROFILE (current_cpu
)[0];
175 /* Record the cycles computed for an insn.
176 LAST_P is non-zero if this is the last insn in a set of parallel insns,
177 and we update the total cycle count.
178 CYCLES is the cycle count of the insn. */
181 MY (f_model_insn_after
) (SIM_CPU
*current_cpu
, int last_p ATTRIBUTE_UNUSED
,
184 PROFILE_DATA
*p
= CPU_PROFILE_DATA (current_cpu
);
186 PROFILE_MODEL_TOTAL_CYCLES (p
) += cycles
;
187 CPU_CRIS_MISC_PROFILE (current_cpu
)->basic_cycle_count
+= cycles
;
188 PROFILE_MODEL_CUR_INSN_CYCLES (p
) = cycles
;
191 /* For some reason, we don't get to the sim_events_tick call in
192 cgen-run.c:engine_run_1. Besides, more than one cycle has
193 passed, so we want sim_events_tickn anyway. The "events we want
194 to process" is usually to initiate an interrupt, but might also
195 be other events. We can't do the former until the main loop is
196 at point where it accepts changing the PC without internal
197 inconsistency, so just set a flag and wait. */
198 if (sim_events_tickn (CPU_STATE (current_cpu
), cycles
))
199 STATE_EVENTS (CPU_STATE (current_cpu
))->work_pending
= 1;
204 /* Initialize cycle counting for an insn.
205 FIRST_P is non-zero if this is the first insn in a set of parallel
209 MY (f_model_init_insn_cycles
) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
210 int first_p ATTRIBUTE_UNUSED
)
215 /* Record the cycles computed for an insn.
216 LAST_P is non-zero if this is the last insn in a set of parallel insns,
217 and we update the total cycle count. */
220 MY (f_model_update_insn_cycles
) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
221 int last_p ATTRIBUTE_UNUSED
)
227 MY (f_model_record_cycles
) (SIM_CPU
*current_cpu
, unsigned long cycles
)
233 MY (f_model_mark_get_h_gr
) (SIM_CPU
*current_cpu
, ARGBUF
*abuf
)
239 MY (f_model_mark_set_h_gr
) (SIM_CPU
*current_cpu
, ARGBUF
*abuf
)
245 /* Set the thread register contents. */
248 MY (set_target_thread_data
) (SIM_CPU
*current_cpu
, USI val
)
250 (CPU (XCONCAT2 (h_sr_v
, BASENUM
) [CRIS_TLS_REGISTER
])) = val
;
253 /* Create the context for a thread. */
256 MY (make_thread_cpu_data
) (SIM_CPU
*current_cpu
, void *context
)
258 struct cris_sim_cpu
*cris_cpu
= CRIS_SIM_CPU (current_cpu
);
259 void *info
= xmalloc (cris_cpu
->thread_cpu_data_size
);
262 memcpy (info
, context
, cris_cpu
->thread_cpu_data_size
);
264 memset (info
, 0, cris_cpu
->thread_cpu_data_size
),abort();
268 /* Placate -Wmissing-prototypes when mloop.in isn't used. */
269 void MY (f_specific_init
) (SIM_CPU
*current_cpu
);
271 /* Hook function for per-cpu simulator initialization. */
274 MY (f_specific_init
) (SIM_CPU
*current_cpu
)
276 struct cris_sim_cpu
*cris_cpu
= CRIS_SIM_CPU (current_cpu
);
278 cris_cpu
->make_thread_cpu_data
= MY (make_thread_cpu_data
);
279 cris_cpu
->thread_cpu_data_size
= sizeof (cris_cpu
->cpu_data
);
280 cris_cpu
->set_target_thread_data
= MY (set_target_thread_data
);
282 cris_cpu
->deliver_interrupt
= MY (deliver_interrupt
);
286 /* Placate -Wmissing-prototypes when mloop.in isn't used. */
287 int MY (XCONCAT3 (f_model_crisv
,BASENUM
, _u_stall
))
288 (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
291 int referenced ATTRIBUTE_UNUSED
);
293 /* Model function for arbitrary single stall cycles. */
296 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
297 _u_stall
)) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
300 int referenced ATTRIBUTE_UNUSED
)
302 return idesc
->timing
->units
[unit_num
].done
;
305 #ifndef SPECIFIC_U_SKIP4_FN
307 /* Model function for u-skip4 unit. */
310 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
311 _u_skip4
)) (SIM_CPU
*current_cpu
,
314 int referenced ATTRIBUTE_UNUSED
)
316 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
318 return idesc
->timing
->units
[unit_num
].done
;
323 #ifndef SPECIFIC_U_EXEC_FN
325 /* Model function for u-exec unit. */
328 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
329 _u_exec
)) (SIM_CPU
*current_cpu
,
331 int unit_num
, int referenced ATTRIBUTE_UNUSED
)
333 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
335 return idesc
->timing
->units
[unit_num
].done
;
339 #ifndef SPECIFIC_U_MEM_FN
341 /* Model function for u-mem unit. */
344 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
345 _u_mem
)) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
348 int referenced ATTRIBUTE_UNUSED
)
350 return idesc
->timing
->units
[unit_num
].done
;
354 #ifndef SPECIFIC_U_CONST16_FN
356 /* Model function for u-const16 unit. */
359 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
360 _u_const16
)) (SIM_CPU
*current_cpu
,
363 int referenced ATTRIBUTE_UNUSED
)
366 return idesc
->timing
->units
[unit_num
].done
;
368 #endif /* SPECIFIC_U_CONST16_FN */
370 #ifndef SPECIFIC_U_CONST32_FN
372 /* This will be incorrect for early models, where a dword always take
374 #define CRIS_MODEL_MASK_PC_STALL 2
376 /* Model function for u-const32 unit. */
379 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
380 _u_const32
)) (SIM_CPU
*current_cpu
,
383 int referenced ATTRIBUTE_UNUSED
)
386 = (((CPU (h_pc
) + 2) & CRIS_MODEL_MASK_PC_STALL
)
387 == CRIS_MODEL_MASK_PC_STALL
);
389 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
390 CPU_CRIS_MISC_PROFILE (current_cpu
)->unaligned_mem_dword_count
394 return idesc
->timing
->units
[unit_num
].done
;
396 #endif /* SPECIFIC_U_CONST32_FN */
398 #ifndef SPECIFIC_U_MOVEM_FN
400 /* Model function for u-movem unit. */
403 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
404 _u_movem
)) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
405 const IDESC
*idesc ATTRIBUTE_UNUSED
,
406 int unit_num ATTRIBUTE_UNUSED
,
407 int referenced ATTRIBUTE_UNUSED
,
410 /* FIXME: Add cycles for misalignment. */
415 /* We don't record movem move cycles in movemsrc_stall_count since
416 those cycles have historically been handled as ordinary cycles. */
419 #endif /* SPECIFIC_U_MOVEM_FN */
421 #endif /* WITH_PROFILE_MODEL_P */