1 /* CRIS base simulator support code
2 Copyright (C) 2004, 2005, 2006 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 2, or (at your option)
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 along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 /* The infrastructure is based on that of i960.c. */
29 #define MY(f) XCONCAT3(crisv,BASENUM,f)
31 /* Dispatcher for break insn. */
34 MY (f_break_handler
) (SIM_CPU
*cpu
, USI breaknum
, USI pc
)
36 SIM_DESC sd
= CPU_STATE (cpu
);
39 MY (f_h_pc_set
) (cpu
, ret
);
41 /* FIXME: Error out if IBR or ERP set. */
45 MY (f_h_gr_set (cpu
, 10,
46 cris_break_13_handler (cpu
,
47 MY (f_h_gr_get (cpu
, 9)),
48 MY (f_h_gr_get (cpu
, 10)),
49 MY (f_h_gr_get (cpu
, 11)),
50 MY (f_h_gr_get (cpu
, 12)),
51 MY (f_h_gr_get (cpu
, 13)),
52 MY (f_h_sr_get (cpu
, 7)),
53 MY (f_h_sr_get (cpu
, 11)),
58 sim_io_printf (sd
, "%x\n", MY (f_h_gr_get (cpu
, 3)));
62 /* Re-use the Linux exit call. */
63 cris_break_13_handler (cpu
, /* TARGET_SYS_exit */ 1, 0,
70 return MY (f_h_pc_get
) (cpu
);
73 /* Accessor function for simulator internal use.
74 Note the contents of BUF are in target byte order. */
77 MY (f_fetch_register
) (SIM_CPU
*current_cpu
, int rn
,
78 unsigned char *buf
, int len ATTRIBUTE_UNUSED
)
80 SETTSI (buf
, XCONCAT3(crisv
,BASENUM
,f_h_gr_get
) (current_cpu
, rn
));
84 /* Accessor function for simulator internal use.
85 Note the contents of BUF are in target byte order. */
88 MY (f_store_register
) (SIM_CPU
*current_cpu
, int rn
,
89 unsigned char *buf
, int len ATTRIBUTE_UNUSED
)
91 XCONCAT3(crisv
,BASENUM
,f_h_gr_set
) (current_cpu
, rn
, GETTSI (buf
));
95 #if WITH_PROFILE_MODEL_P
97 /* FIXME: Some of these should be inline or macros. Later. */
99 /* Initialize cycle counting for an insn.
100 FIRST_P is non-zero if this is the first insn in a set of parallel
104 MY (f_model_insn_before
) (SIM_CPU
*current_cpu
, int first_p ATTRIBUTE_UNUSED
)
106 /* To give the impression that we actually know what PC is, we have to
107 dump register contents *before* the *next* insn, not after the
108 *previous* insn. Uhh... */
110 /* FIXME: Move this to separate, overridable function. */
111 if ((CPU_CRIS_MISC_PROFILE (current_cpu
)->flags
112 & FLAG_CRIS_MISC_PROFILE_XSIM_TRACE
)
113 #ifdef GET_H_INSN_PREFIXED_P
114 /* For versions with prefixed insns, trace the combination as
116 && !GET_H_INSN_PREFIXED_P ()
122 unsigned64 cycle_count
;
124 SIM_DESC sd
= CPU_STATE (current_cpu
);
126 cris_trace_printf (sd
, current_cpu
, "%lx ",
127 0xffffffffUL
& (unsigned long) (CPU (h_pc
)));
129 for (i
= 0; i
< 15; i
++)
130 cris_trace_printf (sd
, current_cpu
, "%lx ",
132 & (unsigned long) (XCONCAT3(crisv
,BASENUM
,
133 f_h_gr_get
) (current_cpu
,
135 flags
[0] = GET_H_IBIT () != 0 ? 'I' : 'i';
136 flags
[1] = GET_H_XBIT () != 0 ? 'X' : 'x';
137 flags
[2] = GET_H_NBIT () != 0 ? 'N' : 'n';
138 flags
[3] = GET_H_ZBIT () != 0 ? 'Z' : 'z';
139 flags
[4] = GET_H_VBIT () != 0 ? 'V' : 'v';
140 flags
[5] = GET_H_CBIT () != 0 ? 'C' : 'c';
143 /* For anything else than basic tracing we'd add stall cycles for
144 e.g. unaligned accesses. FIXME: add --cris-trace=x options to
145 match --cris-cycles=x. */
147 = (CPU_CRIS_MISC_PROFILE (current_cpu
)->basic_cycle_count
148 - CPU_CRIS_PREV_MISC_PROFILE (current_cpu
)->basic_cycle_count
);
150 /* Emit ACR after flags and cycle count for this insn. */
152 cris_trace_printf (sd
, current_cpu
, "%s %d %lx\n", flags
,
155 & (unsigned long) (XCONCAT3(crisv
,BASENUM
,
156 f_h_gr_get
) (current_cpu
,
159 cris_trace_printf (sd
, current_cpu
, "%s %d\n", flags
,
162 CPU_CRIS_PREV_MISC_PROFILE (current_cpu
)[0]
163 = CPU_CRIS_MISC_PROFILE (current_cpu
)[0];
167 /* Record the cycles computed for an insn.
168 LAST_P is non-zero if this is the last insn in a set of parallel insns,
169 and we update the total cycle count.
170 CYCLES is the cycle count of the insn. */
173 MY (f_model_insn_after
) (SIM_CPU
*current_cpu
, int last_p ATTRIBUTE_UNUSED
,
176 PROFILE_DATA
*p
= CPU_PROFILE_DATA (current_cpu
);
178 PROFILE_MODEL_TOTAL_CYCLES (p
) += cycles
;
179 CPU_CRIS_MISC_PROFILE (current_cpu
)->basic_cycle_count
+= cycles
;
180 PROFILE_MODEL_CUR_INSN_CYCLES (p
) = cycles
;
183 /* For some reason, we don't get to the sim_events_tick call in
184 cgen-run.c:engine_run_1. Besides, more than one cycle has
185 passed, so we want sim_events_tickn anyway. The "events we want
186 to process" is usually to initiate an interrupt, but might also
187 be other events. We can't do the former until the main loop is
188 at point where it accepts changing the PC without internal
189 inconsistency, so just set a flag and wait. */
190 if (sim_events_tickn (CPU_STATE (current_cpu
), cycles
))
191 STATE_EVENTS (CPU_STATE (current_cpu
))->work_pending
= 1;
195 /* Initialize cycle counting for an insn.
196 FIRST_P is non-zero if this is the first insn in a set of parallel
200 MY (f_model_init_insn_cycles
) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
201 int first_p ATTRIBUTE_UNUSED
)
206 /* Record the cycles computed for an insn.
207 LAST_P is non-zero if this is the last insn in a set of parallel insns,
208 and we update the total cycle count. */
211 MY (f_model_update_insn_cycles
) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
212 int last_p ATTRIBUTE_UNUSED
)
219 MY (f_model_record_cycles
) (SIM_CPU
*current_cpu
, unsigned long cycles
)
225 MY (f_model_mark_get_h_gr
) (SIM_CPU
*current_cpu
, ARGBUF
*abuf
)
231 MY (f_model_mark_set_h_gr
) (SIM_CPU
*current_cpu
, ARGBUF
*abuf
)
237 /* Create the context for a thread. */
240 MY (make_thread_cpu_data
) (SIM_CPU
*current_cpu
, void *context
)
242 void *info
= xmalloc (current_cpu
->thread_cpu_data_size
);
247 current_cpu
->thread_cpu_data_size
);
249 memset (info
, 0, current_cpu
->thread_cpu_data_size
),abort();
253 /* Hook function for per-cpu simulator initialization. */
256 MY (f_specific_init
) (SIM_CPU
*current_cpu
)
258 current_cpu
->make_thread_cpu_data
= MY (make_thread_cpu_data
);
259 current_cpu
->thread_cpu_data_size
= sizeof (current_cpu
->cpu_data
);
261 current_cpu
->deliver_interrupt
= MY (deliver_interrupt
);
265 /* Model function for arbitrary single stall cycles. */
268 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
269 _u_stall
)) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
272 int referenced ATTRIBUTE_UNUSED
)
274 return idesc
->timing
->units
[unit_num
].done
;
277 #ifndef SPECIFIC_U_SKIP4_FN
279 /* Model function for u-skip4 unit. */
282 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
283 _u_skip4
)) (SIM_CPU
*current_cpu
,
286 int referenced ATTRIBUTE_UNUSED
)
288 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
290 return idesc
->timing
->units
[unit_num
].done
;
295 #ifndef SPECIFIC_U_EXEC_FN
297 /* Model function for u-exec unit. */
300 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
301 _u_exec
)) (SIM_CPU
*current_cpu
,
303 int unit_num
, int referenced ATTRIBUTE_UNUSED
)
305 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
307 return idesc
->timing
->units
[unit_num
].done
;
311 #ifndef SPECIFIC_U_MEM_FN
313 /* Model function for u-mem unit. */
316 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
317 _u_mem
)) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
320 int referenced ATTRIBUTE_UNUSED
)
322 return idesc
->timing
->units
[unit_num
].done
;
326 #ifndef SPECIFIC_U_CONST16_FN
328 /* Model function for u-const16 unit. */
331 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
332 _u_const16
)) (SIM_CPU
*current_cpu
,
335 int referenced ATTRIBUTE_UNUSED
)
338 return idesc
->timing
->units
[unit_num
].done
;
340 #endif /* SPECIFIC_U_CONST16_FN */
342 #ifndef SPECIFIC_U_CONST32_FN
344 /* This will be incorrect for early models, where a dword always take
346 #define CRIS_MODEL_MASK_PC_STALL 2
348 /* Model function for u-const32 unit. */
351 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
352 _u_const32
)) (SIM_CPU
*current_cpu
,
355 int referenced ATTRIBUTE_UNUSED
)
358 = (((CPU (h_pc
) + 2) & CRIS_MODEL_MASK_PC_STALL
)
359 == CRIS_MODEL_MASK_PC_STALL
);
361 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
362 CPU_CRIS_MISC_PROFILE (current_cpu
)->unaligned_mem_dword_count
366 return idesc
->timing
->units
[unit_num
].done
;
368 #endif /* SPECIFIC_U_CONST32_FN */
370 #ifndef SPECIFIC_U_MOVEM_FN
372 /* Model function for u-movem unit. */
375 MY (XCONCAT3 (f_model_crisv
,BASENUM
,
376 _u_movem
)) (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
377 const IDESC
*idesc ATTRIBUTE_UNUSED
,
378 int unit_num ATTRIBUTE_UNUSED
,
379 int referenced ATTRIBUTE_UNUSED
,
382 /* FIXME: Add cycles for misalignment. */
387 /* We don't record movem move cycles in movemsrc_stall_count since
388 those cycles have historically been handled as ordinary cycles. */
391 #endif /* SPECIFIC_U_MOVEM_FN */
393 #endif /* WITH_PROFILE_MODEL_P */