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