]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/cris/cris-tmpl.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / sim / cris / cris-tmpl.c
CommitLineData
f6bcefef 1/* CRIS base simulator support code
1d506c26 2 Copyright (C) 2004-2024 Free Software Foundation, Inc.
f6bcefef
HPN
3 Contributed by Axis Communications.
4
5This file is part of the GNU simulators.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
4744ac1b
JB
9the Free Software Foundation; either version 3 of the License, or
10(at your option) any later version.
f6bcefef
HPN
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
4744ac1b
JB
17You should have received a copy of the GNU General Public License
18along with this program. If not, see <http://www.gnu.org/licenses/>. */
f6bcefef
HPN
19
20/* The infrastructure is based on that of i960.c. */
21
6df01ab8
MF
22/* This must come before any other includes. */
23#include "defs.h"
24
f6bcefef
HPN
25#define WANT_CPU
26
27#include "sim-main.h"
28#include "cgen-mem.h"
29#include "cgen-ops.h"
30
32a046ab
TT
31#include <stdlib.h>
32
f6bcefef
HPN
33#define MY(f) XCONCAT3(crisv,BASENUM,f)
34
35/* Dispatcher for break insn. */
36
37USI
38MY (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
b356d0c5
MF
70 /* This shouldn't be reached, but we can't mark break 13 as noreturn
71 since there are some calls which should return. */
72 ATTRIBUTE_FALLTHROUGH;
73
f6bcefef
HPN
74 default:
75 abort ();
76 }
77
78 return MY (f_h_pc_get) (cpu);
79}
80
81/* Accessor function for simulator internal use.
82 Note the contents of BUF are in target byte order. */
83
84int
ee1cffd3
MF
85MY (f_fetch_register) (SIM_CPU *current_cpu, int rn, void *buf,
86 int len ATTRIBUTE_UNUSED)
f6bcefef
HPN
87{
88 SETTSI (buf, XCONCAT3(crisv,BASENUM,f_h_gr_get) (current_cpu, rn));
89 return -1;
90}
91
92/* Accessor function for simulator internal use.
93 Note the contents of BUF are in target byte order. */
94
95int
ee1cffd3
MF
96MY (f_store_register) (SIM_CPU *current_cpu, int rn, const void *buf,
97 int len ATTRIBUTE_UNUSED)
f6bcefef
HPN
98{
99 XCONCAT3(crisv,BASENUM,f_h_gr_set) (current_cpu, rn, GETTSI (buf));
100 return -1;
101}
102\f
103#if WITH_PROFILE_MODEL_P
104
105/* FIXME: Some of these should be inline or macros. Later. */
106
107/* Initialize cycle counting for an insn.
108 FIRST_P is non-zero if this is the first insn in a set of parallel
109 insns. */
110
111void
112MY (f_model_insn_before) (SIM_CPU *current_cpu, int first_p ATTRIBUTE_UNUSED)
113{
114 /* To give the impression that we actually know what PC is, we have to
115 dump register contents *before* the *next* insn, not after the
116 *previous* insn. Uhh... */
117
118 /* FIXME: Move this to separate, overridable function. */
119 if ((CPU_CRIS_MISC_PROFILE (current_cpu)->flags
120 & FLAG_CRIS_MISC_PROFILE_XSIM_TRACE)
121#ifdef GET_H_INSN_PREFIXED_P
122 /* For versions with prefixed insns, trace the combination as
123 one insn. */
124 && !GET_H_INSN_PREFIXED_P ()
125#endif
126 && 1)
127 {
128 int i;
129 char flags[7];
2875d098 130 uint64_t cycle_count;
4fc9958a 131
f6bcefef
HPN
132 SIM_DESC sd = CPU_STATE (current_cpu);
133
ae81c235
HPN
134 cris_trace_printf (sd, current_cpu, "%lx ",
135 0xffffffffUL & (unsigned long) (CPU (h_pc)));
f6bcefef
HPN
136
137 for (i = 0; i < 15; i++)
138 cris_trace_printf (sd, current_cpu, "%lx ",
ae81c235
HPN
139 0xffffffffUL
140 & (unsigned long) (XCONCAT3(crisv,BASENUM,
141 f_h_gr_get) (current_cpu,
142 i)));
f6bcefef
HPN
143 flags[0] = GET_H_IBIT () != 0 ? 'I' : 'i';
144 flags[1] = GET_H_XBIT () != 0 ? 'X' : 'x';
145 flags[2] = GET_H_NBIT () != 0 ? 'N' : 'n';
146 flags[3] = GET_H_ZBIT () != 0 ? 'Z' : 'z';
147 flags[4] = GET_H_VBIT () != 0 ? 'V' : 'v';
148 flags[5] = GET_H_CBIT () != 0 ? 'C' : 'c';
149 flags[6] = 0;
150
4fc9958a
HPN
151 /* For anything else than basic tracing we'd add stall cycles for
152 e.g. unaligned accesses. FIXME: add --cris-trace=x options to
153 match --cris-cycles=x. */
154 cycle_count
155 = (CPU_CRIS_MISC_PROFILE (current_cpu)->basic_cycle_count
156 - CPU_CRIS_PREV_MISC_PROFILE (current_cpu)->basic_cycle_count);
157
f6bcefef
HPN
158 /* Emit ACR after flags and cycle count for this insn. */
159 if (BASENUM == 32)
160 cris_trace_printf (sd, current_cpu, "%s %d %lx\n", flags,
4fc9958a 161 (int) cycle_count,
ae81c235
HPN
162 0xffffffffUL
163 & (unsigned long) (XCONCAT3(crisv,BASENUM,
164 f_h_gr_get) (current_cpu,
165 15)));
f6bcefef
HPN
166 else
167 cris_trace_printf (sd, current_cpu, "%s %d\n", flags,
4fc9958a 168 (int) cycle_count);
f6bcefef
HPN
169
170 CPU_CRIS_PREV_MISC_PROFILE (current_cpu)[0]
171 = CPU_CRIS_MISC_PROFILE (current_cpu)[0];
172 }
173}
174
175/* Record the cycles computed for an insn.
176 LAST_P is non-zero if this is the last insn in a set of parallel insns,
177 and we update the total cycle count.
178 CYCLES is the cycle count of the insn. */
179
180void
181MY (f_model_insn_after) (SIM_CPU *current_cpu, int last_p ATTRIBUTE_UNUSED,
182 int cycles)
183{
184 PROFILE_DATA *p = CPU_PROFILE_DATA (current_cpu);
185
186 PROFILE_MODEL_TOTAL_CYCLES (p) += cycles;
187 CPU_CRIS_MISC_PROFILE (current_cpu)->basic_cycle_count += cycles;
188 PROFILE_MODEL_CUR_INSN_CYCLES (p) = cycles;
aad3b3cb
HPN
189
190#if WITH_HW
191 /* For some reason, we don't get to the sim_events_tick call in
192 cgen-run.c:engine_run_1. Besides, more than one cycle has
193 passed, so we want sim_events_tickn anyway. The "events we want
194 to process" is usually to initiate an interrupt, but might also
195 be other events. We can't do the former until the main loop is
196 at point where it accepts changing the PC without internal
197 inconsistency, so just set a flag and wait. */
198 if (sim_events_tickn (CPU_STATE (current_cpu), cycles))
199 STATE_EVENTS (CPU_STATE (current_cpu))->work_pending = 1;
200#endif
f6bcefef
HPN
201}
202
4e6e8ba7 203#if 0
f6bcefef
HPN
204/* Initialize cycle counting for an insn.
205 FIRST_P is non-zero if this is the first insn in a set of parallel
206 insns. */
207
208void
209MY (f_model_init_insn_cycles) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
210 int first_p ATTRIBUTE_UNUSED)
211{
212 abort ();
213}
214
215/* Record the cycles computed for an insn.
216 LAST_P is non-zero if this is the last insn in a set of parallel insns,
217 and we update the total cycle count. */
218
219void
220MY (f_model_update_insn_cycles) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
221 int last_p ATTRIBUTE_UNUSED)
222{
223 abort ();
224}
225
f6bcefef
HPN
226void
227MY (f_model_record_cycles) (SIM_CPU *current_cpu, unsigned long cycles)
228{
229 abort ();
230}
231
232void
233MY (f_model_mark_get_h_gr) (SIM_CPU *current_cpu, ARGBUF *abuf)
234{
235 abort ();
236}
237
238void
239MY (f_model_mark_set_h_gr) (SIM_CPU *current_cpu, ARGBUF *abuf)
240{
241 abort ();
242}
243#endif
244\f
ddf2c972
HPN
245/* Set the thread register contents. */
246
4e6e8ba7 247static void
ddf2c972
HPN
248MY (set_target_thread_data) (SIM_CPU *current_cpu, USI val)
249{
250 (CPU (XCONCAT2 (h_sr_v, BASENUM) [CRIS_TLS_REGISTER])) = val;
251}
252
f6bcefef
HPN
253/* Create the context for a thread. */
254
4e6e8ba7 255static void *
f6bcefef
HPN
256MY (make_thread_cpu_data) (SIM_CPU *current_cpu, void *context)
257{
86817137
MF
258 struct cris_sim_cpu *cris_cpu = CRIS_SIM_CPU (current_cpu);
259 void *info = xmalloc (cris_cpu->thread_cpu_data_size);
f6bcefef
HPN
260
261 if (context != NULL)
86817137 262 memcpy (info, context, cris_cpu->thread_cpu_data_size);
f6bcefef 263 else
86817137 264 memset (info, 0, cris_cpu->thread_cpu_data_size),abort();
f6bcefef
HPN
265 return info;
266}
267
887f85fb
TT
268/* Placate -Wmissing-prototypes when mloop.in isn't used. */
269void MY (f_specific_init) (SIM_CPU *current_cpu);
270
f6bcefef
HPN
271/* Hook function for per-cpu simulator initialization. */
272
273void
274MY (f_specific_init) (SIM_CPU *current_cpu)
275{
86817137
MF
276 struct cris_sim_cpu *cris_cpu = CRIS_SIM_CPU (current_cpu);
277
278 cris_cpu->make_thread_cpu_data = MY (make_thread_cpu_data);
279 cris_cpu->thread_cpu_data_size = sizeof (cris_cpu->cpu_data);
280 cris_cpu->set_target_thread_data = MY (set_target_thread_data);
aad3b3cb 281#if WITH_HW
86817137 282 cris_cpu->deliver_interrupt = MY (deliver_interrupt);
aad3b3cb 283#endif
f6bcefef
HPN
284}
285\f
887f85fb
TT
286/* Placate -Wmissing-prototypes when mloop.in isn't used. */
287int MY (XCONCAT3 (f_model_crisv,BASENUM, _u_stall))
288 (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
289 const IDESC *idesc,
290 int unit_num,
291 int referenced ATTRIBUTE_UNUSED);
292
f6bcefef
HPN
293/* Model function for arbitrary single stall cycles. */
294
295int
296MY (XCONCAT3 (f_model_crisv,BASENUM,
297 _u_stall)) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
298 const IDESC *idesc,
299 int unit_num,
300 int referenced ATTRIBUTE_UNUSED)
301{
302 return idesc->timing->units[unit_num].done;
303}
304
305#ifndef SPECIFIC_U_SKIP4_FN
306
307/* Model function for u-skip4 unit. */
308
309int
310MY (XCONCAT3 (f_model_crisv,BASENUM,
311 _u_skip4)) (SIM_CPU *current_cpu,
312 const IDESC *idesc,
313 int unit_num,
314 int referenced ATTRIBUTE_UNUSED)
315{
316 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
317 CPU (h_pc) += 4;
318 return idesc->timing->units[unit_num].done;
319}
320
321#endif
322
323#ifndef SPECIFIC_U_EXEC_FN
324
325/* Model function for u-exec unit. */
326
327int
328MY (XCONCAT3 (f_model_crisv,BASENUM,
329 _u_exec)) (SIM_CPU *current_cpu,
330 const IDESC *idesc,
331 int unit_num, int referenced ATTRIBUTE_UNUSED)
332{
333 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
334 CPU (h_pc) += 2;
335 return idesc->timing->units[unit_num].done;
336}
337#endif
338
339#ifndef SPECIFIC_U_MEM_FN
340
341/* Model function for u-mem unit. */
342
343int
344MY (XCONCAT3 (f_model_crisv,BASENUM,
345 _u_mem)) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
346 const IDESC *idesc,
347 int unit_num,
348 int referenced ATTRIBUTE_UNUSED)
349{
350 return idesc->timing->units[unit_num].done;
351}
352#endif
353
354#ifndef SPECIFIC_U_CONST16_FN
355
356/* Model function for u-const16 unit. */
357
358int
359MY (XCONCAT3 (f_model_crisv,BASENUM,
360 _u_const16)) (SIM_CPU *current_cpu,
361 const IDESC *idesc,
362 int unit_num,
363 int referenced ATTRIBUTE_UNUSED)
364{
365 CPU (h_pc) += 2;
366 return idesc->timing->units[unit_num].done;
367}
368#endif /* SPECIFIC_U_CONST16_FN */
369
370#ifndef SPECIFIC_U_CONST32_FN
371
372/* This will be incorrect for early models, where a dword always take
373 two cycles. */
374#define CRIS_MODEL_MASK_PC_STALL 2
375
376/* Model function for u-const32 unit. */
377
378int
379MY (XCONCAT3 (f_model_crisv,BASENUM,
380 _u_const32)) (SIM_CPU *current_cpu,
381 const IDESC *idesc,
382 int unit_num,
383 int referenced ATTRIBUTE_UNUSED)
384{
385 int unaligned_extra
386 = (((CPU (h_pc) + 2) & CRIS_MODEL_MASK_PC_STALL)
387 == CRIS_MODEL_MASK_PC_STALL);
388
389 /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
390 CPU_CRIS_MISC_PROFILE (current_cpu)->unaligned_mem_dword_count
391 += unaligned_extra;
392
393 CPU (h_pc) += 4;
394 return idesc->timing->units[unit_num].done;
395}
396#endif /* SPECIFIC_U_CONST32_FN */
397
398#ifndef SPECIFIC_U_MOVEM_FN
399
400/* Model function for u-movem unit. */
401
402int
403MY (XCONCAT3 (f_model_crisv,BASENUM,
404 _u_movem)) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
405 const IDESC *idesc ATTRIBUTE_UNUSED,
406 int unit_num ATTRIBUTE_UNUSED,
407 int referenced ATTRIBUTE_UNUSED,
408 INT limreg)
409{
410 /* FIXME: Add cycles for misalignment. */
411
412 if (limreg == -1)
413 abort ();
414
415 /* We don't record movem move cycles in movemsrc_stall_count since
416 those cycles have historically been handled as ordinary cycles. */
417 return limreg + 1;
418}
419#endif /* SPECIFIC_U_MOVEM_FN */
420
421#endif /* WITH_PROFILE_MODEL_P */