1 /* CRIS base simulator support code
2 Copyright (C) 2004, 2005, 2006, 2007, 2008 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. */
28 #define MY(f) XCONCAT3(crisv,BASENUM,f)
30 /* Dispatcher for break insn. */
33 MY (f_break_handler
) (SIM_CPU
*cpu
, USI breaknum
, USI pc
)
35 SIM_DESC sd
= CPU_STATE (cpu
);
38 MY (f_h_pc_set
) (cpu
, ret
);
40 /* FIXME: Error out if IBR or ERP set. */
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)),
57 sim_io_printf (sd
, "%x\n", MY (f_h_gr_get (cpu
, 3)));
61 /* Re-use the Linux exit call. */
62 cris_break_13_handler (cpu
, /* TARGET_SYS_exit */ 1, 0,
69 return MY (f_h_pc_get
) (cpu
);
72 /* Accessor function for simulator internal use.
73 Note the contents of BUF are in target byte order. */
76 MY (f_fetch_register
) (SIM_CPU
*current_cpu
, int rn
,
77 unsigned char *buf
, int len ATTRIBUTE_UNUSED
)
79 SETTSI (buf
, XCONCAT3(crisv
,BASENUM
,f_h_gr_get
) (current_cpu
, rn
));
83 /* Accessor function for simulator internal use.
84 Note the contents of BUF are in target byte order. */
87 MY (f_store_register
) (SIM_CPU
*current_cpu
, int rn
,
88 unsigned char *buf
, int len ATTRIBUTE_UNUSED
)
90 XCONCAT3(crisv
,BASENUM
,f_h_gr_set
) (current_cpu
, rn
, GETTSI (buf
));
94 #if WITH_PROFILE_MODEL_P
96 /* FIXME: Some of these should be inline or macros. Later. */
98 /* Initialize cycle counting for an insn.
99 FIRST_P is non-zero if this is the first insn in a set of parallel
103 MY (f_model_insn_before
) (SIM_CPU
*current_cpu
, int first_p ATTRIBUTE_UNUSED
)
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... */
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
115 && !GET_H_INSN_PREFIXED_P ()
121 unsigned64 cycle_count
;
123 SIM_DESC sd
= CPU_STATE (current_cpu
);
125 cris_trace_printf (sd
, current_cpu
, "%lx ",
126 0xffffffffUL
& (unsigned long) (CPU (h_pc
)));
128 for (i
= 0; i
< 15; i
++)
129 cris_trace_printf (sd
, current_cpu
, "%lx ",
131 & (unsigned long) (XCONCAT3(crisv
,BASENUM
,
132 f_h_gr_get
) (current_cpu
,
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';
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. */
146 = (CPU_CRIS_MISC_PROFILE (current_cpu
)->basic_cycle_count
147 - CPU_CRIS_PREV_MISC_PROFILE (current_cpu
)->basic_cycle_count
);
149 /* Emit ACR after flags and cycle count for this insn. */
151 cris_trace_printf (sd
, current_cpu
, "%s %d %lx\n", flags
,
154 & (unsigned long) (XCONCAT3(crisv
,BASENUM
,
155 f_h_gr_get
) (current_cpu
,
158 cris_trace_printf (sd
, current_cpu
, "%s %d\n", flags
,
161 CPU_CRIS_PREV_MISC_PROFILE (current_cpu
)[0]
162 = CPU_CRIS_MISC_PROFILE (current_cpu
)[0];
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. */
172 MY (f_model_insn_after
) (SIM_CPU
*current_cpu
, int last_p ATTRIBUTE_UNUSED
,
175 PROFILE_DATA
*p
= CPU_PROFILE_DATA (current_cpu
);
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
;
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;
194 /* Initialize cycle counting for an insn.
195 FIRST_P is non-zero if this is the first insn in a set of parallel
199 MY (f_model_init_insn_cycles
) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
200 int first_p ATTRIBUTE_UNUSED
)
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. */
210 MY (f_model_update_insn_cycles
) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
211 int last_p ATTRIBUTE_UNUSED
)
218 MY (f_model_record_cycles
) (SIM_CPU
*current_cpu
, unsigned long cycles
)
224 MY (f_model_mark_get_h_gr
) (SIM_CPU
*current_cpu
, ARGBUF
*abuf
)
230 MY (f_model_mark_set_h_gr
) (SIM_CPU
*current_cpu
, ARGBUF
*abuf
)
236 /* Create the context for a thread. */
239 MY (make_thread_cpu_data
) (SIM_CPU
*current_cpu
, void *context
)
241 void *info
= xmalloc (current_cpu
->thread_cpu_data_size
);
246 current_cpu
->thread_cpu_data_size
);
248 memset (info
, 0, current_cpu
->thread_cpu_data_size
),abort();
252 /* Hook function for per-cpu simulator initialization. */
255 MY (f_specific_init
) (SIM_CPU
*current_cpu
)
257 current_cpu
->make_thread_cpu_data
= MY (make_thread_cpu_data
);
258 current_cpu
->thread_cpu_data_size
= sizeof (current_cpu
->cpu_data
);
260 current_cpu
->deliver_interrupt
= MY (deliver_interrupt
);
264 /* Model function for arbitrary single stall cycles. */
267 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
268 _u_stall
)) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
271 int referenced ATTRIBUTE_UNUSED
)
273 return idesc
->timing
->units
[unit_num
].done
;
276 #ifndef SPECIFIC_U_SKIP4_FN
278 /* Model function for u-skip4 unit. */
281 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
282 _u_skip4
)) (SIM_CPU
*current_cpu
,
285 int referenced ATTRIBUTE_UNUSED
)
287 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
289 return idesc
->timing
->units
[unit_num
].done
;
294 #ifndef SPECIFIC_U_EXEC_FN
296 /* Model function for u-exec unit. */
299 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
300 _u_exec
)) (SIM_CPU
*current_cpu
,
302 int unit_num
, int referenced ATTRIBUTE_UNUSED
)
304 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
306 return idesc
->timing
->units
[unit_num
].done
;
310 #ifndef SPECIFIC_U_MEM_FN
312 /* Model function for u-mem unit. */
315 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
316 _u_mem
)) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
319 int referenced ATTRIBUTE_UNUSED
)
321 return idesc
->timing
->units
[unit_num
].done
;
325 #ifndef SPECIFIC_U_CONST16_FN
327 /* Model function for u-const16 unit. */
330 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
331 _u_const16
)) (SIM_CPU
*current_cpu
,
334 int referenced ATTRIBUTE_UNUSED
)
337 return idesc
->timing
->units
[unit_num
].done
;
339 #endif /* SPECIFIC_U_CONST16_FN */
341 #ifndef SPECIFIC_U_CONST32_FN
343 /* This will be incorrect for early models, where a dword always take
345 #define CRIS_MODEL_MASK_PC_STALL 2
347 /* Model function for u-const32 unit. */
350 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
351 _u_const32
)) (SIM_CPU
*current_cpu
,
354 int referenced ATTRIBUTE_UNUSED
)
357 = (((CPU (h_pc
) + 2) & CRIS_MODEL_MASK_PC_STALL
)
358 == CRIS_MODEL_MASK_PC_STALL
);
360 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
361 CPU_CRIS_MISC_PROFILE (current_cpu
)->unaligned_mem_dword_count
365 return idesc
->timing
->units
[unit_num
].done
;
367 #endif /* SPECIFIC_U_CONST32_FN */
369 #ifndef SPECIFIC_U_MOVEM_FN
371 /* Model function for u-movem unit. */
374 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
375 _u_movem
)) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
376 const IDESC
*idesc ATTRIBUTE_UNUSED
,
377 int unit_num ATTRIBUTE_UNUSED
,
378 int referenced ATTRIBUTE_UNUSED
,
381 /* FIXME: Add cycles for misalignment. */
386 /* We don't record movem move cycles in movemsrc_stall_count since
387 those cycles have historically been handled as ordinary cycles. */
390 #endif /* SPECIFIC_U_MOVEM_FN */
392 #endif /* WITH_PROFILE_MODEL_P */