Add system includes in sim
[binutils-gdb.git] / sim / cris / cris-tmpl.c
1 /* CRIS base simulator support code
2 Copyright (C) 2004-2021 Free Software Foundation, Inc.
3 Contributed by Axis Communications.
4
5 This file is part of the GNU simulators.
6
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.
11
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.
16
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/>. */
19
20 /* The infrastructure is based on that of i960.c. */
21
22 #define WANT_CPU
23
24 #include "sim-main.h"
25 #include "cgen-mem.h"
26 #include "cgen-ops.h"
27
28 #include <stdlib.h>
29
30 #define MY(f) XCONCAT3(crisv,BASENUM,f)
31
32 /* Dispatcher for break insn. */
33
34 USI
35 MY (f_break_handler) (SIM_CPU *cpu, USI breaknum, USI pc)
36 {
37 SIM_DESC sd = CPU_STATE (cpu);
38 USI ret = pc + 2;
39
40 MY (f_h_pc_set) (cpu, ret);
41
42 /* FIXME: Error out if IBR or ERP set. */
43 switch (breaknum)
44 {
45 case 13:
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)),
55 pc)));
56 break;
57
58 case 14:
59 sim_io_printf (sd, "%x\n", MY (f_h_gr_get (cpu, 3)));
60 break;
61
62 case 15:
63 /* Re-use the Linux exit call. */
64 cris_break_13_handler (cpu, /* TARGET_SYS_exit */ 1, 0,
65 0, 0, 0, 0, 0, pc);
66
67 default:
68 abort ();
69 }
70
71 return MY (f_h_pc_get) (cpu);
72 }
73
74 /* Accessor function for simulator internal use.
75 Note the contents of BUF are in target byte order. */
76
77 int
78 MY (f_fetch_register) (SIM_CPU *current_cpu, int rn,
79 unsigned char *buf, int len ATTRIBUTE_UNUSED)
80 {
81 SETTSI (buf, XCONCAT3(crisv,BASENUM,f_h_gr_get) (current_cpu, rn));
82 return -1;
83 }
84
85 /* Accessor function for simulator internal use.
86 Note the contents of BUF are in target byte order. */
87
88 int
89 MY (f_store_register) (SIM_CPU *current_cpu, int rn,
90 unsigned char *buf, int len ATTRIBUTE_UNUSED)
91 {
92 XCONCAT3(crisv,BASENUM,f_h_gr_set) (current_cpu, rn, GETTSI (buf));
93 return -1;
94 }
95 \f
96 #if WITH_PROFILE_MODEL_P
97
98 /* FIXME: Some of these should be inline or macros. Later. */
99
100 /* Initialize cycle counting for an insn.
101 FIRST_P is non-zero if this is the first insn in a set of parallel
102 insns. */
103
104 void
105 MY (f_model_insn_before) (SIM_CPU *current_cpu, int first_p ATTRIBUTE_UNUSED)
106 {
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... */
110
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
116 one insn. */
117 && !GET_H_INSN_PREFIXED_P ()
118 #endif
119 && 1)
120 {
121 int i;
122 char flags[7];
123 unsigned64 cycle_count;
124
125 SIM_DESC sd = CPU_STATE (current_cpu);
126
127 cris_trace_printf (sd, current_cpu, "%lx ",
128 0xffffffffUL & (unsigned long) (CPU (h_pc)));
129
130 for (i = 0; i < 15; i++)
131 cris_trace_printf (sd, current_cpu, "%lx ",
132 0xffffffffUL
133 & (unsigned long) (XCONCAT3(crisv,BASENUM,
134 f_h_gr_get) (current_cpu,
135 i)));
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';
142 flags[6] = 0;
143
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. */
147 cycle_count
148 = (CPU_CRIS_MISC_PROFILE (current_cpu)->basic_cycle_count
149 - CPU_CRIS_PREV_MISC_PROFILE (current_cpu)->basic_cycle_count);
150
151 /* Emit ACR after flags and cycle count for this insn. */
152 if (BASENUM == 32)
153 cris_trace_printf (sd, current_cpu, "%s %d %lx\n", flags,
154 (int) cycle_count,
155 0xffffffffUL
156 & (unsigned long) (XCONCAT3(crisv,BASENUM,
157 f_h_gr_get) (current_cpu,
158 15)));
159 else
160 cris_trace_printf (sd, current_cpu, "%s %d\n", flags,
161 (int) cycle_count);
162
163 CPU_CRIS_PREV_MISC_PROFILE (current_cpu)[0]
164 = CPU_CRIS_MISC_PROFILE (current_cpu)[0];
165 }
166 }
167
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. */
172
173 void
174 MY (f_model_insn_after) (SIM_CPU *current_cpu, int last_p ATTRIBUTE_UNUSED,
175 int cycles)
176 {
177 PROFILE_DATA *p = CPU_PROFILE_DATA (current_cpu);
178
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;
182
183 #if WITH_HW
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;
193 #endif
194 }
195
196 /* Initialize cycle counting for an insn.
197 FIRST_P is non-zero if this is the first insn in a set of parallel
198 insns. */
199
200 void
201 MY (f_model_init_insn_cycles) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
202 int first_p ATTRIBUTE_UNUSED)
203 {
204 abort ();
205 }
206
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. */
210
211 void
212 MY (f_model_update_insn_cycles) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
213 int last_p ATTRIBUTE_UNUSED)
214 {
215 abort ();
216 }
217
218 #if 0
219 void
220 MY (f_model_record_cycles) (SIM_CPU *current_cpu, unsigned long cycles)
221 {
222 abort ();
223 }
224
225 void
226 MY (f_model_mark_get_h_gr) (SIM_CPU *current_cpu, ARGBUF *abuf)
227 {
228 abort ();
229 }
230
231 void
232 MY (f_model_mark_set_h_gr) (SIM_CPU *current_cpu, ARGBUF *abuf)
233 {
234 abort ();
235 }
236 #endif
237 \f
238 /* Set the thread register contents. */
239
240 void
241 MY (set_target_thread_data) (SIM_CPU *current_cpu, USI val)
242 {
243 (CPU (XCONCAT2 (h_sr_v, BASENUM) [CRIS_TLS_REGISTER])) = val;
244 }
245
246 /* Create the context for a thread. */
247
248 void *
249 MY (make_thread_cpu_data) (SIM_CPU *current_cpu, void *context)
250 {
251 void *info = xmalloc (current_cpu->thread_cpu_data_size);
252
253 if (context != NULL)
254 memcpy (info,
255 context,
256 current_cpu->thread_cpu_data_size);
257 else
258 memset (info, 0, current_cpu->thread_cpu_data_size),abort();
259 return info;
260 }
261
262 /* Hook function for per-cpu simulator initialization. */
263
264 void
265 MY (f_specific_init) (SIM_CPU *current_cpu)
266 {
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);
270 #if WITH_HW
271 current_cpu->deliver_interrupt = MY (deliver_interrupt);
272 #endif
273 }
274 \f
275 /* Model function for arbitrary single stall cycles. */
276
277 int
278 MY (XCONCAT3 (f_model_crisv,BASENUM,
279 _u_stall)) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
280 const IDESC *idesc,
281 int unit_num,
282 int referenced ATTRIBUTE_UNUSED)
283 {
284 return idesc->timing->units[unit_num].done;
285 }
286
287 #ifndef SPECIFIC_U_SKIP4_FN
288
289 /* Model function for u-skip4 unit. */
290
291 int
292 MY (XCONCAT3 (f_model_crisv,BASENUM,
293 _u_skip4)) (SIM_CPU *current_cpu,
294 const IDESC *idesc,
295 int unit_num,
296 int referenced ATTRIBUTE_UNUSED)
297 {
298 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
299 CPU (h_pc) += 4;
300 return idesc->timing->units[unit_num].done;
301 }
302
303 #endif
304
305 #ifndef SPECIFIC_U_EXEC_FN
306
307 /* Model function for u-exec unit. */
308
309 int
310 MY (XCONCAT3 (f_model_crisv,BASENUM,
311 _u_exec)) (SIM_CPU *current_cpu,
312 const IDESC *idesc,
313 int unit_num, int referenced ATTRIBUTE_UNUSED)
314 {
315 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
316 CPU (h_pc) += 2;
317 return idesc->timing->units[unit_num].done;
318 }
319 #endif
320
321 #ifndef SPECIFIC_U_MEM_FN
322
323 /* Model function for u-mem unit. */
324
325 int
326 MY (XCONCAT3 (f_model_crisv,BASENUM,
327 _u_mem)) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
328 const IDESC *idesc,
329 int unit_num,
330 int referenced ATTRIBUTE_UNUSED)
331 {
332 return idesc->timing->units[unit_num].done;
333 }
334 #endif
335
336 #ifndef SPECIFIC_U_CONST16_FN
337
338 /* Model function for u-const16 unit. */
339
340 int
341 MY (XCONCAT3 (f_model_crisv,BASENUM,
342 _u_const16)) (SIM_CPU *current_cpu,
343 const IDESC *idesc,
344 int unit_num,
345 int referenced ATTRIBUTE_UNUSED)
346 {
347 CPU (h_pc) += 2;
348 return idesc->timing->units[unit_num].done;
349 }
350 #endif /* SPECIFIC_U_CONST16_FN */
351
352 #ifndef SPECIFIC_U_CONST32_FN
353
354 /* This will be incorrect for early models, where a dword always take
355 two cycles. */
356 #define CRIS_MODEL_MASK_PC_STALL 2
357
358 /* Model function for u-const32 unit. */
359
360 int
361 MY (XCONCAT3 (f_model_crisv,BASENUM,
362 _u_const32)) (SIM_CPU *current_cpu,
363 const IDESC *idesc,
364 int unit_num,
365 int referenced ATTRIBUTE_UNUSED)
366 {
367 int unaligned_extra
368 = (((CPU (h_pc) + 2) & CRIS_MODEL_MASK_PC_STALL)
369 == CRIS_MODEL_MASK_PC_STALL);
370
371 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
372 CPU_CRIS_MISC_PROFILE (current_cpu)->unaligned_mem_dword_count
373 += unaligned_extra;
374
375 CPU (h_pc) += 4;
376 return idesc->timing->units[unit_num].done;
377 }
378 #endif /* SPECIFIC_U_CONST32_FN */
379
380 #ifndef SPECIFIC_U_MOVEM_FN
381
382 /* Model function for u-movem unit. */
383
384 int
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,
390 INT limreg)
391 {
392 /* FIXME: Add cycles for misalignment. */
393
394 if (limreg == -1)
395 abort ();
396
397 /* We don't record movem move cycles in movemsrc_stall_count since
398 those cycles have historically been handled as ordinary cycles. */
399 return limreg + 1;
400 }
401 #endif /* SPECIFIC_U_MOVEM_FN */
402
403 #endif /* WITH_PROFILE_MODEL_P */