1/* Generic simulator halt/restart.
2   Copyright (C) 1997, 1998, 2007, 2008, 2009, 2010, 2011
3   Free Software Foundation, Inc.
4   Contributed by Cygnus Support.
5
6This file is part of GDB, the GNU debugger.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 3 of the License, or
11(at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21#include <stdio.h>
22
23#include "sim-main.h"
24#include "sim-assert.h"
25
26/* Get the run state.
27   REASON/SIGRC are the values returned by sim_stop_reason.
28   ??? Should each cpu have its own copy?  */
29
30void
31sim_engine_get_run_state (SIM_DESC sd, enum sim_stop *reason, int *sigrc)
32{
33  sim_engine *engine = STATE_ENGINE (sd);
34  ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
35  *reason = engine->reason;
36  *sigrc = engine->sigrc;
37}
38
39/* Set the run state to REASON/SIGRC.
40   REASON/SIGRC are the values returned by sim_stop_reason.
41   ??? Should each cpu have its own copy?  */
42
43void
44sim_engine_set_run_state (SIM_DESC sd, enum sim_stop reason, int sigrc)
45{
46  sim_engine *engine = STATE_ENGINE (sd);
47  ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
48  engine->reason = reason;
49  engine->sigrc = sigrc;
50}
51
52/* Generic halt */
53
54void
55sim_engine_halt (SIM_DESC sd,
56		 sim_cpu *last_cpu,
57		 sim_cpu *next_cpu, /* NULL - use default */
58		 sim_cia cia,
59		 enum sim_stop reason,
60		 int sigrc)
61{
62  sim_engine *engine = STATE_ENGINE (sd);
63  ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
64  if (engine->jmpbuf != NULL)
65    {
66      jmp_buf *halt_buf = engine->jmpbuf;
67      engine->last_cpu = last_cpu;
68      engine->next_cpu = next_cpu;
69      engine->reason = reason;
70      engine->sigrc = sigrc;
71
72      SIM_ENGINE_HALT_HOOK (sd, last_cpu, cia);
73
74#ifdef SIM_CPU_EXCEPTION_SUSPEND
75      if (last_cpu != NULL && reason != sim_exited)
76	SIM_CPU_EXCEPTION_SUSPEND (sd, last_cpu, sim_signal_to_host (sd, sigrc));
77#endif
78
79      longjmp (*halt_buf, sim_engine_halt_jmpval);
80    }
81  else
82    {
83      sim_io_error (sd, "sim_halt - bad long jump");
84      abort ();
85    }
86}
87
88
89/* Generic restart */
90
91void
92sim_engine_restart (SIM_DESC sd,
93		    sim_cpu *last_cpu,
94		    sim_cpu *next_cpu,
95		    sim_cia cia)
96{
97  sim_engine *engine = STATE_ENGINE (sd);
98  ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
99  if (engine->jmpbuf != NULL)
100    {
101      jmp_buf *halt_buf = engine->jmpbuf;
102      engine->last_cpu = last_cpu;
103      engine->next_cpu = next_cpu;
104      SIM_ENGINE_RESTART_HOOK (sd, last_cpu, cia);
105      longjmp (*halt_buf, sim_engine_restart_jmpval);
106    }
107  else
108    sim_io_error (sd, "sim_restart - bad long jump");
109}
110
111
112/* Generic error code */
113
114void
115sim_engine_vabort (SIM_DESC sd,
116		   sim_cpu *cpu,
117		   sim_cia cia,
118		   const char *fmt,
119		   va_list ap)
120{
121  ASSERT (sd == NULL || STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
122  if (sd == NULL)
123    {
124      vfprintf (stderr, fmt, ap);
125      fprintf (stderr, "\nQuit\n");
126      abort ();
127    }
128  else if (STATE_ENGINE (sd)->jmpbuf == NULL)
129    {
130      sim_io_evprintf (sd, fmt, ap);
131      sim_io_eprintf (sd, "\n");
132      sim_io_error (sd, "Quit Simulator");
133      abort ();
134    }
135  else
136    {
137      sim_io_evprintf (sd, fmt, ap);
138      sim_io_eprintf (sd, "\n");
139      sim_engine_halt (sd, cpu, NULL, cia, sim_stopped, SIM_SIGABRT);
140    }
141}
142
143void
144sim_engine_abort (SIM_DESC sd,
145		  sim_cpu *cpu,
146		  sim_cia cia,
147		  const char *fmt,
148		  ...)
149{
150  va_list ap;
151  ASSERT (sd == NULL || STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
152  va_start(ap, fmt);
153  sim_engine_vabort (sd, cpu, cia, fmt, ap);
154  va_end (ap);
155}
156
157
158/* Generic next/last cpu */
159
160int
161sim_engine_last_cpu_nr (SIM_DESC sd)
162{
163  sim_engine *engine = STATE_ENGINE (sd);
164  if (engine->last_cpu != NULL)
165    return engine->last_cpu - STATE_CPU (sd, 0);
166  else
167    return MAX_NR_PROCESSORS;
168}
169
170int
171sim_engine_next_cpu_nr (SIM_DESC sd)
172{
173  sim_engine *engine = STATE_ENGINE (sd);
174  if (engine->next_cpu != NULL)
175    return engine->next_cpu - STATE_CPU (sd, 0);
176  else
177    return sim_engine_last_cpu_nr (sd) + 1;
178}
179
180int
181sim_engine_nr_cpus (SIM_DESC sd)
182{
183  sim_engine *engine = STATE_ENGINE (sd);
184  return engine->nr_cpus;
185}
186
187
188
189
190/* Initialization */
191
192static SIM_RC
193sim_engine_init (SIM_DESC sd)
194{
195  /* initialize the start/stop/resume engine */
196  sim_engine *engine = STATE_ENGINE (sd);
197  engine->jmpbuf = NULL;
198  engine->last_cpu = NULL;
199  engine->next_cpu = NULL;
200  engine->nr_cpus = MAX_NR_PROCESSORS;
201  engine->reason = sim_running;
202  engine->sigrc = 0;
203  engine->stepper = NULL; /* sim_events_init will clean it up */
204  return SIM_RC_OK;
205}
206
207
208SIM_RC
209sim_engine_install (SIM_DESC sd)
210{
211  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
212  sim_module_add_init_fn (sd, sim_engine_init);
213  return SIM_RC_OK;
214}
215