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. */
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,
74 return MY (f_h_pc_get
) (cpu
);
77 /* Accessor function for simulator internal use.
78 Note the contents of BUF are in target byte order. */
81 MY (f_fetch_register
) (SIM_CPU
*current_cpu
, int rn
,
82 unsigned char *buf
, int len ATTRIBUTE_UNUSED
)
84 SETTSI (buf
, XCONCAT3(crisv
,BASENUM
,f_h_gr_get
) (current_cpu
, rn
));
88 /* Accessor function for simulator internal use.
89 Note the contents of BUF are in target byte order. */
92 MY (f_store_register
) (SIM_CPU
*current_cpu
, int rn
,
93 unsigned char *buf
, int len ATTRIBUTE_UNUSED
)
95 XCONCAT3(crisv
,BASENUM
,f_h_gr_set
) (current_cpu
, rn
, GETTSI (buf
));
99 #if WITH_PROFILE_MODEL_P
101 /* FIXME: Some of these should be inline or macros. Later. */
103 /* Initialize cycle counting for an insn.
104 FIRST_P is non-zero if this is the first insn in a set of parallel
108 MY (f_model_insn_before
) (SIM_CPU
*current_cpu
, int first_p ATTRIBUTE_UNUSED
)
110 /* To give the impression that we actually know what PC is, we have to
111 dump register contents *before* the *next* insn, not after the
112 *previous* insn. Uhh... */
114 /* FIXME: Move this to separate, overridable function. */
115 if ((CPU_CRIS_MISC_PROFILE (current_cpu
)->flags
116 & FLAG_CRIS_MISC_PROFILE_XSIM_TRACE
)
117 #ifdef GET_H_INSN_PREFIXED_P
118 /* For versions with prefixed insns, trace the combination as
120 && !GET_H_INSN_PREFIXED_P ()
126 unsigned64 cycle_count
;
128 SIM_DESC sd
= CPU_STATE (current_cpu
);
130 cris_trace_printf (sd
, current_cpu
, "%lx ",
131 0xffffffffUL
& (unsigned long) (CPU (h_pc
)));
133 for (i
= 0; i
< 15; i
++)
134 cris_trace_printf (sd
, current_cpu
, "%lx ",
136 & (unsigned long) (XCONCAT3(crisv
,BASENUM
,
137 f_h_gr_get
) (current_cpu
,
139 flags
[0] = GET_H_IBIT () != 0 ? 'I' : 'i';
140 flags
[1] = GET_H_XBIT () != 0 ? 'X' : 'x';
141 flags
[2] = GET_H_NBIT () != 0 ? 'N' : 'n';
142 flags
[3] = GET_H_ZBIT () != 0 ? 'Z' : 'z';
143 flags
[4] = GET_H_VBIT () != 0 ? 'V' : 'v';
144 flags
[5] = GET_H_CBIT () != 0 ? 'C' : 'c';
147 /* For anything else than basic tracing we'd add stall cycles for
148 e.g. unaligned accesses. FIXME: add --cris-trace=x options to
149 match --cris-cycles=x. */
151 = (CPU_CRIS_MISC_PROFILE (current_cpu
)->basic_cycle_count
152 - CPU_CRIS_PREV_MISC_PROFILE (current_cpu
)->basic_cycle_count
);
154 /* Emit ACR after flags and cycle count for this insn. */
156 cris_trace_printf (sd
, current_cpu
, "%s %d %lx\n", flags
,
159 & (unsigned long) (XCONCAT3(crisv
,BASENUM
,
160 f_h_gr_get
) (current_cpu
,
163 cris_trace_printf (sd
, current_cpu
, "%s %d\n", flags
,
166 CPU_CRIS_PREV_MISC_PROFILE (current_cpu
)[0]
167 = CPU_CRIS_MISC_PROFILE (current_cpu
)[0];
171 /* Record the cycles computed for an insn.
172 LAST_P is non-zero if this is the last insn in a set of parallel insns,
173 and we update the total cycle count.
174 CYCLES is the cycle count of the insn. */
177 MY (f_model_insn_after
) (SIM_CPU
*current_cpu
, int last_p ATTRIBUTE_UNUSED
,
180 PROFILE_DATA
*p
= CPU_PROFILE_DATA (current_cpu
);
182 PROFILE_MODEL_TOTAL_CYCLES (p
) += cycles
;
183 CPU_CRIS_MISC_PROFILE (current_cpu
)->basic_cycle_count
+= cycles
;
184 PROFILE_MODEL_CUR_INSN_CYCLES (p
) = cycles
;
187 /* For some reason, we don't get to the sim_events_tick call in
188 cgen-run.c:engine_run_1. Besides, more than one cycle has
189 passed, so we want sim_events_tickn anyway. The "events we want
190 to process" is usually to initiate an interrupt, but might also
191 be other events. We can't do the former until the main loop is
192 at point where it accepts changing the PC without internal
193 inconsistency, so just set a flag and wait. */
194 if (sim_events_tickn (CPU_STATE (current_cpu
), cycles
))
195 STATE_EVENTS (CPU_STATE (current_cpu
))->work_pending
= 1;
199 /* Initialize cycle counting for an insn.
200 FIRST_P is non-zero if this is the first insn in a set of parallel
204 MY (f_model_init_insn_cycles
) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
205 int first_p ATTRIBUTE_UNUSED
)
210 /* Record the cycles computed for an insn.
211 LAST_P is non-zero if this is the last insn in a set of parallel insns,
212 and we update the total cycle count. */
215 MY (f_model_update_insn_cycles
) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
216 int last_p ATTRIBUTE_UNUSED
)
223 MY (f_model_record_cycles
) (SIM_CPU
*current_cpu
, unsigned long cycles
)
229 MY (f_model_mark_get_h_gr
) (SIM_CPU
*current_cpu
, ARGBUF
*abuf
)
235 MY (f_model_mark_set_h_gr
) (SIM_CPU
*current_cpu
, ARGBUF
*abuf
)
241 /* Set the thread register contents. */
244 MY (set_target_thread_data
) (SIM_CPU
*current_cpu
, USI val
)
246 (CPU (XCONCAT2 (h_sr_v
, BASENUM
) [CRIS_TLS_REGISTER
])) = val
;
249 /* Create the context for a thread. */
252 MY (make_thread_cpu_data
) (SIM_CPU
*current_cpu
, void *context
)
254 void *info
= xmalloc (current_cpu
->thread_cpu_data_size
);
259 current_cpu
->thread_cpu_data_size
);
261 memset (info
, 0, current_cpu
->thread_cpu_data_size
),abort();
265 /* Hook function for per-cpu simulator initialization. */
268 MY (f_specific_init
) (SIM_CPU
*current_cpu
)
270 current_cpu
->make_thread_cpu_data
= MY (make_thread_cpu_data
);
271 current_cpu
->thread_cpu_data_size
= sizeof (current_cpu
->cpu_data
);
272 current_cpu
->set_target_thread_data
= MY (set_target_thread_data
);
274 current_cpu
->deliver_interrupt
= MY (deliver_interrupt
);
278 /* Model function for arbitrary single stall cycles. */
281 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
282 _u_stall
)) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
285 int referenced ATTRIBUTE_UNUSED
)
287 return idesc
->timing
->units
[unit_num
].done
;
290 #ifndef SPECIFIC_U_SKIP4_FN
292 /* Model function for u-skip4 unit. */
295 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
296 _u_skip4
)) (SIM_CPU
*current_cpu
,
299 int referenced ATTRIBUTE_UNUSED
)
301 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
303 return idesc
->timing
->units
[unit_num
].done
;
308 #ifndef SPECIFIC_U_EXEC_FN
310 /* Model function for u-exec unit. */
313 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
314 _u_exec
)) (SIM_CPU
*current_cpu
,
316 int unit_num
, int referenced ATTRIBUTE_UNUSED
)
318 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
320 return idesc
->timing
->units
[unit_num
].done
;
324 #ifndef SPECIFIC_U_MEM_FN
326 /* Model function for u-mem unit. */
329 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
330 _u_mem
)) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
333 int referenced ATTRIBUTE_UNUSED
)
335 return idesc
->timing
->units
[unit_num
].done
;
339 #ifndef SPECIFIC_U_CONST16_FN
341 /* Model function for u-const16 unit. */
344 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
345 _u_const16
)) (SIM_CPU
*current_cpu
,
348 int referenced ATTRIBUTE_UNUSED
)
351 return idesc
->timing
->units
[unit_num
].done
;
353 #endif /* SPECIFIC_U_CONST16_FN */
355 #ifndef SPECIFIC_U_CONST32_FN
357 /* This will be incorrect for early models, where a dword always take
359 #define CRIS_MODEL_MASK_PC_STALL 2
361 /* Model function for u-const32 unit. */
364 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
365 _u_const32
)) (SIM_CPU
*current_cpu
,
368 int referenced ATTRIBUTE_UNUSED
)
371 = (((CPU (h_pc
) + 2) & CRIS_MODEL_MASK_PC_STALL
)
372 == CRIS_MODEL_MASK_PC_STALL
);
374 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
375 CPU_CRIS_MISC_PROFILE (current_cpu
)->unaligned_mem_dword_count
379 return idesc
->timing
->units
[unit_num
].done
;
381 #endif /* SPECIFIC_U_CONST32_FN */
383 #ifndef SPECIFIC_U_MOVEM_FN
385 /* Model function for u-movem unit. */
388 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
389 _u_movem
)) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
390 const IDESC
*idesc ATTRIBUTE_UNUSED
,
391 int unit_num ATTRIBUTE_UNUSED
,
392 int referenced ATTRIBUTE_UNUSED
,
395 /* FIXME: Add cycles for misalignment. */
400 /* We don't record movem move cycles in movemsrc_stall_count since
401 those cycles have historically been handled as ordinary cycles. */
404 #endif /* SPECIFIC_U_MOVEM_FN */
406 #endif /* WITH_PROFILE_MODEL_P */