gdbserver: dump 'xx...x' in collect_register_as_string for unavailable register
[binutils-gdb.git] / sim / cris / cris-tmpl.c
blob5399f63ffbd3ce8a3bf7d90c1ae4f841c751a660
1 /* CRIS base simulator support code
2 Copyright (C) 2004-2024 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. */
22 /* This must come before any other includes. */
23 #include "defs.h"
25 #define WANT_CPU
27 #include "sim-main.h"
28 #include "cgen-mem.h"
29 #include "cgen-ops.h"
31 #include <stdlib.h>
33 #define MY(f) XCONCAT3(crisv,BASENUM,f)
35 /* Dispatcher for break insn. */
37 USI
38 MY (f_break_handler) (SIM_CPU *cpu, USI breaknum, USI pc)
40 SIM_DESC sd = CPU_STATE (cpu);
41 USI ret = pc + 2;
43 MY (f_h_pc_set) (cpu, ret);
45 /* FIXME: Error out if IBR or ERP set. */
46 switch (breaknum)
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;
61 case 14:
62 sim_io_printf (sd, "%x\n", MY (f_h_gr_get (cpu, 3)));
63 break;
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);
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;
74 default:
75 abort ();
78 return MY (f_h_pc_get) (cpu);
81 /* Accessor function for simulator internal use.
82 Note the contents of BUF are in target byte order. */
84 int
85 MY (f_fetch_register) (SIM_CPU *current_cpu, int rn, void *buf,
86 int len ATTRIBUTE_UNUSED)
88 SETTSI (buf, XCONCAT3(crisv,BASENUM,f_h_gr_get) (current_cpu, rn));
89 return -1;
92 /* Accessor function for simulator internal use.
93 Note the contents of BUF are in target byte order. */
95 int
96 MY (f_store_register) (SIM_CPU *current_cpu, int rn, const void *buf,
97 int len ATTRIBUTE_UNUSED)
99 XCONCAT3(crisv,BASENUM,f_h_gr_set) (current_cpu, rn, GETTSI (buf));
100 return -1;
103 #if WITH_PROFILE_MODEL_P
105 /* FIXME: Some of these should be inline or macros. Later. */
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. */
111 void
112 MY (f_model_insn_before) (SIM_CPU *current_cpu, int first_p ATTRIBUTE_UNUSED)
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... */
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)
128 int i;
129 char flags[7];
130 uint64_t cycle_count;
132 SIM_DESC sd = CPU_STATE (current_cpu);
134 cris_trace_printf (sd, current_cpu, "%lx ",
135 0xffffffffUL & (unsigned long) (CPU (h_pc)));
137 for (i = 0; i < 15; i++)
138 cris_trace_printf (sd, current_cpu, "%lx ",
139 0xffffffffUL
140 & (unsigned long) (XCONCAT3(crisv,BASENUM,
141 f_h_gr_get) (current_cpu,
142 i)));
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;
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);
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,
161 (int) cycle_count,
162 0xffffffffUL
163 & (unsigned long) (XCONCAT3(crisv,BASENUM,
164 f_h_gr_get) (current_cpu,
165 15)));
166 else
167 cris_trace_printf (sd, current_cpu, "%s %d\n", flags,
168 (int) cycle_count);
170 CPU_CRIS_PREV_MISC_PROFILE (current_cpu)[0]
171 = CPU_CRIS_MISC_PROFILE (current_cpu)[0];
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. */
180 void
181 MY (f_model_insn_after) (SIM_CPU *current_cpu, int last_p ATTRIBUTE_UNUSED,
182 int cycles)
184 PROFILE_DATA *p = CPU_PROFILE_DATA (current_cpu);
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;
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
203 #if 0
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. */
208 void
209 MY (f_model_init_insn_cycles) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
210 int first_p ATTRIBUTE_UNUSED)
212 abort ();
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. */
219 void
220 MY (f_model_update_insn_cycles) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
221 int last_p ATTRIBUTE_UNUSED)
223 abort ();
226 void
227 MY (f_model_record_cycles) (SIM_CPU *current_cpu, unsigned long cycles)
229 abort ();
232 void
233 MY (f_model_mark_get_h_gr) (SIM_CPU *current_cpu, ARGBUF *abuf)
235 abort ();
238 void
239 MY (f_model_mark_set_h_gr) (SIM_CPU *current_cpu, ARGBUF *abuf)
241 abort ();
243 #endif
245 /* Set the thread register contents. */
247 static void
248 MY (set_target_thread_data) (SIM_CPU *current_cpu, USI val)
250 (CPU (XCONCAT2 (h_sr_v, BASENUM) [CRIS_TLS_REGISTER])) = val;
253 /* Create the context for a thread. */
255 static void *
256 MY (make_thread_cpu_data) (SIM_CPU *current_cpu, void *context)
258 struct cris_sim_cpu *cris_cpu = CRIS_SIM_CPU (current_cpu);
259 void *info = xmalloc (cris_cpu->thread_cpu_data_size);
261 if (context != NULL)
262 memcpy (info, context, cris_cpu->thread_cpu_data_size);
263 else
264 memset (info, 0, cris_cpu->thread_cpu_data_size),abort();
265 return info;
268 /* Placate -Wmissing-prototypes when mloop.in isn't used. */
269 void MY (f_specific_init) (SIM_CPU *current_cpu);
271 /* Hook function for per-cpu simulator initialization. */
273 void
274 MY (f_specific_init) (SIM_CPU *current_cpu)
276 struct cris_sim_cpu *cris_cpu = CRIS_SIM_CPU (current_cpu);
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);
281 #if WITH_HW
282 cris_cpu->deliver_interrupt = MY (deliver_interrupt);
283 #endif
286 /* Placate -Wmissing-prototypes when mloop.in isn't used. */
287 int 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);
293 /* Model function for arbitrary single stall cycles. */
296 MY (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)
302 return idesc->timing->units[unit_num].done;
305 #ifndef SPECIFIC_U_SKIP4_FN
307 /* Model function for u-skip4 unit. */
310 MY (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)
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;
321 #endif
323 #ifndef SPECIFIC_U_EXEC_FN
325 /* Model function for u-exec unit. */
328 MY (XCONCAT3 (f_model_crisv,BASENUM,
329 _u_exec)) (SIM_CPU *current_cpu,
330 const IDESC *idesc,
331 int unit_num, int referenced ATTRIBUTE_UNUSED)
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;
337 #endif
339 #ifndef SPECIFIC_U_MEM_FN
341 /* Model function for u-mem unit. */
344 MY (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)
350 return idesc->timing->units[unit_num].done;
352 #endif
354 #ifndef SPECIFIC_U_CONST16_FN
356 /* Model function for u-const16 unit. */
359 MY (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)
365 CPU (h_pc) += 2;
366 return idesc->timing->units[unit_num].done;
368 #endif /* SPECIFIC_U_CONST16_FN */
370 #ifndef SPECIFIC_U_CONST32_FN
372 /* This will be incorrect for early models, where a dword always take
373 two cycles. */
374 #define CRIS_MODEL_MASK_PC_STALL 2
376 /* Model function for u-const32 unit. */
379 MY (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)
385 int unaligned_extra
386 = (((CPU (h_pc) + 2) & CRIS_MODEL_MASK_PC_STALL)
387 == CRIS_MODEL_MASK_PC_STALL);
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;
393 CPU (h_pc) += 4;
394 return idesc->timing->units[unit_num].done;
396 #endif /* SPECIFIC_U_CONST32_FN */
398 #ifndef SPECIFIC_U_MOVEM_FN
400 /* Model function for u-movem unit. */
403 MY (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)
410 /* FIXME: Add cycles for misalignment. */
412 if (limreg == -1)
413 abort ();
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;
419 #endif /* SPECIFIC_U_MOVEM_FN */
421 #endif /* WITH_PROFILE_MODEL_P */