1 /* CRIS base simulator support code
2 Copyright (C) 2004-2021 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. */
30 #define MY(f) XCONCAT3(crisv,BASENUM,f)
32 /* Dispatcher for break insn. */
35 MY (f_break_handler
) (SIM_CPU
*cpu
, USI breaknum
, USI pc
)
37 SIM_DESC sd
= CPU_STATE (cpu
);
40 MY (f_h_pc_set
) (cpu
, ret
);
42 /* FIXME: Error out if IBR or ERP set. */
46 MY (f_h_gr_set (cpu
, 10,
47 cris_break_13_handler (cpu
,
48 MY (f_h_gr_get (cpu
, 9)),
49 MY (f_h_gr_get (cpu
, 10)),
50 MY (f_h_gr_get (cpu
, 11)),
51 MY (f_h_gr_get (cpu
, 12)),
52 MY (f_h_gr_get (cpu
, 13)),
53 MY (f_h_sr_get (cpu
, 7)),
54 MY (f_h_sr_get (cpu
, 11)),
59 sim_io_printf (sd
, "%x\n", MY (f_h_gr_get (cpu
, 3)));
63 /* Re-use the Linux exit call. */
64 cris_break_13_handler (cpu
, /* TARGET_SYS_exit */ 1, 0,
71 return MY (f_h_pc_get
) (cpu
);
74 /* Accessor function for simulator internal use.
75 Note the contents of BUF are in target byte order. */
78 MY (f_fetch_register
) (SIM_CPU
*current_cpu
, int rn
,
79 unsigned char *buf
, int len ATTRIBUTE_UNUSED
)
81 SETTSI (buf
, XCONCAT3(crisv
,BASENUM
,f_h_gr_get
) (current_cpu
, rn
));
85 /* Accessor function for simulator internal use.
86 Note the contents of BUF are in target byte order. */
89 MY (f_store_register
) (SIM_CPU
*current_cpu
, int rn
,
90 unsigned char *buf
, int len ATTRIBUTE_UNUSED
)
92 XCONCAT3(crisv
,BASENUM
,f_h_gr_set
) (current_cpu
, rn
, GETTSI (buf
));
96 #if WITH_PROFILE_MODEL_P
98 /* FIXME: Some of these should be inline or macros. Later. */
100 /* Initialize cycle counting for an insn.
101 FIRST_P is non-zero if this is the first insn in a set of parallel
105 MY (f_model_insn_before
) (SIM_CPU
*current_cpu
, int first_p ATTRIBUTE_UNUSED
)
107 /* To give the impression that we actually know what PC is, we have to
108 dump register contents *before* the *next* insn, not after the
109 *previous* insn. Uhh... */
111 /* FIXME: Move this to separate, overridable function. */
112 if ((CPU_CRIS_MISC_PROFILE (current_cpu
)->flags
113 & FLAG_CRIS_MISC_PROFILE_XSIM_TRACE
)
114 #ifdef GET_H_INSN_PREFIXED_P
115 /* For versions with prefixed insns, trace the combination as
117 && !GET_H_INSN_PREFIXED_P ()
123 unsigned64 cycle_count
;
125 SIM_DESC sd
= CPU_STATE (current_cpu
);
127 cris_trace_printf (sd
, current_cpu
, "%lx ",
128 0xffffffffUL
& (unsigned long) (CPU (h_pc
)));
130 for (i
= 0; i
< 15; i
++)
131 cris_trace_printf (sd
, current_cpu
, "%lx ",
133 & (unsigned long) (XCONCAT3(crisv
,BASENUM
,
134 f_h_gr_get
) (current_cpu
,
136 flags
[0] = GET_H_IBIT () != 0 ? 'I' : 'i';
137 flags
[1] = GET_H_XBIT () != 0 ? 'X' : 'x';
138 flags
[2] = GET_H_NBIT () != 0 ? 'N' : 'n';
139 flags
[3] = GET_H_ZBIT () != 0 ? 'Z' : 'z';
140 flags
[4] = GET_H_VBIT () != 0 ? 'V' : 'v';
141 flags
[5] = GET_H_CBIT () != 0 ? 'C' : 'c';
144 /* For anything else than basic tracing we'd add stall cycles for
145 e.g. unaligned accesses. FIXME: add --cris-trace=x options to
146 match --cris-cycles=x. */
148 = (CPU_CRIS_MISC_PROFILE (current_cpu
)->basic_cycle_count
149 - CPU_CRIS_PREV_MISC_PROFILE (current_cpu
)->basic_cycle_count
);
151 /* Emit ACR after flags and cycle count for this insn. */
153 cris_trace_printf (sd
, current_cpu
, "%s %d %lx\n", flags
,
156 & (unsigned long) (XCONCAT3(crisv
,BASENUM
,
157 f_h_gr_get
) (current_cpu
,
160 cris_trace_printf (sd
, current_cpu
, "%s %d\n", flags
,
163 CPU_CRIS_PREV_MISC_PROFILE (current_cpu
)[0]
164 = CPU_CRIS_MISC_PROFILE (current_cpu
)[0];
168 /* Record the cycles computed for an insn.
169 LAST_P is non-zero if this is the last insn in a set of parallel insns,
170 and we update the total cycle count.
171 CYCLES is the cycle count of the insn. */
174 MY (f_model_insn_after
) (SIM_CPU
*current_cpu
, int last_p ATTRIBUTE_UNUSED
,
177 PROFILE_DATA
*p
= CPU_PROFILE_DATA (current_cpu
);
179 PROFILE_MODEL_TOTAL_CYCLES (p
) += cycles
;
180 CPU_CRIS_MISC_PROFILE (current_cpu
)->basic_cycle_count
+= cycles
;
181 PROFILE_MODEL_CUR_INSN_CYCLES (p
) = cycles
;
184 /* For some reason, we don't get to the sim_events_tick call in
185 cgen-run.c:engine_run_1. Besides, more than one cycle has
186 passed, so we want sim_events_tickn anyway. The "events we want
187 to process" is usually to initiate an interrupt, but might also
188 be other events. We can't do the former until the main loop is
189 at point where it accepts changing the PC without internal
190 inconsistency, so just set a flag and wait. */
191 if (sim_events_tickn (CPU_STATE (current_cpu
), cycles
))
192 STATE_EVENTS (CPU_STATE (current_cpu
))->work_pending
= 1;
196 /* Initialize cycle counting for an insn.
197 FIRST_P is non-zero if this is the first insn in a set of parallel
201 MY (f_model_init_insn_cycles
) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
202 int first_p ATTRIBUTE_UNUSED
)
207 /* Record the cycles computed for an insn.
208 LAST_P is non-zero if this is the last insn in a set of parallel insns,
209 and we update the total cycle count. */
212 MY (f_model_update_insn_cycles
) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
213 int last_p ATTRIBUTE_UNUSED
)
220 MY (f_model_record_cycles
) (SIM_CPU
*current_cpu
, unsigned long cycles
)
226 MY (f_model_mark_get_h_gr
) (SIM_CPU
*current_cpu
, ARGBUF
*abuf
)
232 MY (f_model_mark_set_h_gr
) (SIM_CPU
*current_cpu
, ARGBUF
*abuf
)
238 /* Set the thread register contents. */
241 MY (set_target_thread_data
) (SIM_CPU
*current_cpu
, USI val
)
243 (CPU (XCONCAT2 (h_sr_v
, BASENUM
) [CRIS_TLS_REGISTER
])) = val
;
246 /* Create the context for a thread. */
249 MY (make_thread_cpu_data
) (SIM_CPU
*current_cpu
, void *context
)
251 void *info
= xmalloc (current_cpu
->thread_cpu_data_size
);
256 current_cpu
->thread_cpu_data_size
);
258 memset (info
, 0, current_cpu
->thread_cpu_data_size
),abort();
262 /* Hook function for per-cpu simulator initialization. */
265 MY (f_specific_init
) (SIM_CPU
*current_cpu
)
267 current_cpu
->make_thread_cpu_data
= MY (make_thread_cpu_data
);
268 current_cpu
->thread_cpu_data_size
= sizeof (current_cpu
->cpu_data
);
269 current_cpu
->set_target_thread_data
= MY (set_target_thread_data
);
271 current_cpu
->deliver_interrupt
= MY (deliver_interrupt
);
275 /* Model function for arbitrary single stall cycles. */
278 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
279 _u_stall
)) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
282 int referenced ATTRIBUTE_UNUSED
)
284 return idesc
->timing
->units
[unit_num
].done
;
287 #ifndef SPECIFIC_U_SKIP4_FN
289 /* Model function for u-skip4 unit. */
292 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
293 _u_skip4
)) (SIM_CPU
*current_cpu
,
296 int referenced ATTRIBUTE_UNUSED
)
298 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
300 return idesc
->timing
->units
[unit_num
].done
;
305 #ifndef SPECIFIC_U_EXEC_FN
307 /* Model function for u-exec unit. */
310 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
311 _u_exec
)) (SIM_CPU
*current_cpu
,
313 int unit_num
, int referenced ATTRIBUTE_UNUSED
)
315 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
317 return idesc
->timing
->units
[unit_num
].done
;
321 #ifndef SPECIFIC_U_MEM_FN
323 /* Model function for u-mem unit. */
326 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
327 _u_mem
)) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
330 int referenced ATTRIBUTE_UNUSED
)
332 return idesc
->timing
->units
[unit_num
].done
;
336 #ifndef SPECIFIC_U_CONST16_FN
338 /* Model function for u-const16 unit. */
341 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
342 _u_const16
)) (SIM_CPU
*current_cpu
,
345 int referenced ATTRIBUTE_UNUSED
)
348 return idesc
->timing
->units
[unit_num
].done
;
350 #endif /* SPECIFIC_U_CONST16_FN */
352 #ifndef SPECIFIC_U_CONST32_FN
354 /* This will be incorrect for early models, where a dword always take
356 #define CRIS_MODEL_MASK_PC_STALL 2
358 /* Model function for u-const32 unit. */
361 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
362 _u_const32
)) (SIM_CPU
*current_cpu
,
365 int referenced ATTRIBUTE_UNUSED
)
368 = (((CPU (h_pc
) + 2) & CRIS_MODEL_MASK_PC_STALL
)
369 == CRIS_MODEL_MASK_PC_STALL
);
371 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
372 CPU_CRIS_MISC_PROFILE (current_cpu
)->unaligned_mem_dword_count
376 return idesc
->timing
->units
[unit_num
].done
;
378 #endif /* SPECIFIC_U_CONST32_FN */
380 #ifndef SPECIFIC_U_MOVEM_FN
382 /* Model function for u-movem unit. */
385 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
386 _u_movem
)) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
387 const IDESC
*idesc ATTRIBUTE_UNUSED
,
388 int unit_num ATTRIBUTE_UNUSED
,
389 int referenced ATTRIBUTE_UNUSED
,
392 /* FIXME: Add cycles for misalignment. */
397 /* We don't record movem move cycles in movemsrc_stall_count since
398 those cycles have historically been handled as ordinary cycles. */
401 #endif /* SPECIFIC_U_MOVEM_FN */
403 #endif /* WITH_PROFILE_MODEL_P */