1/* Main simulator entry points specific to the M32R.
2   Copyright (C) 1996, 1997, 1998, 1999, 2003, 2007
3   Free Software Foundation, Inc.
4   Contributed by Cygnus Support.
5
6   This file is part of GDB, the GNU debugger.
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21#include "sim-main.h"
22#include "sim-options.h"
23#include "libiberty.h"
24#include "bfd.h"
25
26#ifdef HAVE_STRING_H
27#include <string.h>
28#else
29#ifdef HAVE_STRINGS_H
30#include <strings.h>
31#endif
32#endif
33#ifdef HAVE_STDLIB_H
34#include <stdlib.h>
35#endif
36
37static void free_state (SIM_DESC);
38static void print_m32r_misc_cpu (SIM_CPU *cpu, int verbose);
39
40/* Records simulator descriptor so utilities like m32r_dump_regs can be
41   called from gdb.  */
42SIM_DESC current_state;
43
44/* Cover function of sim_state_free to free the cpu buffers as well.  */
45
46static void
47free_state (SIM_DESC sd)
48{
49  if (STATE_MODULES (sd) != NULL)
50    sim_module_uninstall (sd);
51  sim_cpu_free_all (sd);
52  sim_state_free (sd);
53}
54
55/* Create an instance of the simulator.  */
56
57SIM_DESC
58sim_open (kind, callback, abfd, argv)
59     SIM_OPEN_KIND kind;
60     host_callback *callback;
61     struct bfd *abfd;
62     char **argv;
63{
64  SIM_DESC sd = sim_state_alloc (kind, callback);
65  char c;
66  int i;
67
68  /* The cpu data is kept in a separately allocated chunk of memory.  */
69  if (sim_cpu_alloc_all (sd, 1, cgen_cpu_max_extra_bytes ()) != SIM_RC_OK)
70    {
71      free_state (sd);
72      return 0;
73    }
74
75#if 0 /* FIXME: pc is in mach-specific struct */
76  /* FIXME: watchpoints code shouldn't need this */
77  {
78    SIM_CPU *current_cpu = STATE_CPU (sd, 0);
79    STATE_WATCHPOINTS (sd)->pc = &(PC);
80    STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
81  }
82#endif
83
84  if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
85    {
86      free_state (sd);
87      return 0;
88    }
89
90#ifdef HAVE_DV_SOCKSER /* FIXME: was done differently before */
91  if (dv_sockser_install (sd) != SIM_RC_OK)
92    {
93      free_state (sd);
94      return 0;
95    }
96#endif
97
98#if 0 /* FIXME: 'twould be nice if we could do this */
99  /* These options override any module options.
100     Obviously ambiguity should be avoided, however the caller may wish to
101     augment the meaning of an option.  */
102  if (extra_options != NULL)
103    sim_add_option_table (sd, extra_options);
104#endif
105
106  /* getopt will print the error message so we just have to exit if this fails.
107     FIXME: Hmmm...  in the case of gdb we need getopt to call
108     print_filtered.  */
109  if (sim_parse_args (sd, argv) != SIM_RC_OK)
110    {
111      free_state (sd);
112      return 0;
113    }
114
115  /* Allocate a handler for the control registers and other devices
116     if no memory for that range has been allocated by the user.
117     All are allocated in one chunk to keep things from being
118     unnecessarily complicated.  */
119  if (sim_core_read_buffer (sd, NULL, read_map, &c, M32R_DEVICE_ADDR, 1) == 0)
120    sim_core_attach (sd, NULL,
121		     0 /*level*/,
122		     access_read_write,
123		     0 /*space ???*/,
124		     M32R_DEVICE_ADDR, M32R_DEVICE_LEN /*nr_bytes*/,
125		     0 /*modulo*/,
126		     &m32r_devices,
127		     NULL /*buffer*/);
128
129  /* Allocate core managed memory if none specified by user.
130     Use address 4 here in case the user wanted address 0 unmapped.  */
131  if (sim_core_read_buffer (sd, NULL, read_map, &c, 4, 1) == 0)
132    sim_do_commandf (sd, "memory region 0,0x%x", M32R_DEFAULT_MEM_SIZE);
133
134  /* check for/establish the reference program image */
135  if (sim_analyze_program (sd,
136			   (STATE_PROG_ARGV (sd) != NULL
137			    ? *STATE_PROG_ARGV (sd)
138			    : NULL),
139			   abfd) != SIM_RC_OK)
140    {
141      free_state (sd);
142      return 0;
143    }
144
145  /* Establish any remaining configuration options.  */
146  if (sim_config (sd) != SIM_RC_OK)
147    {
148      free_state (sd);
149      return 0;
150    }
151
152  if (sim_post_argv_init (sd) != SIM_RC_OK)
153    {
154      free_state (sd);
155      return 0;
156    }
157
158  /* Open a copy of the cpu descriptor table.  */
159  {
160    CGEN_CPU_DESC cd = m32r_cgen_cpu_open_1 (STATE_ARCHITECTURE (sd)->printable_name,
161					     CGEN_ENDIAN_BIG);
162    for (i = 0; i < MAX_NR_PROCESSORS; ++i)
163      {
164	SIM_CPU *cpu = STATE_CPU (sd, i);
165	CPU_CPU_DESC (cpu) = cd;
166	CPU_DISASSEMBLER (cpu) = sim_cgen_disassemble_insn;
167      }
168    m32r_cgen_init_dis (cd);
169  }
170
171  /* Initialize various cgen things not done by common framework.
172     Must be done after m32r_cgen_cpu_open.  */
173  cgen_init (sd);
174
175  for (c = 0; c < MAX_NR_PROCESSORS; ++c)
176    {
177      /* Only needed for profiling, but the structure member is small.  */
178      memset (CPU_M32R_MISC_PROFILE (STATE_CPU (sd, i)), 0,
179	      sizeof (* CPU_M32R_MISC_PROFILE (STATE_CPU (sd, i))));
180      /* Hook in callback for reporting these stats */
181      PROFILE_INFO_CPU_CALLBACK (CPU_PROFILE_DATA (STATE_CPU (sd, i)))
182	= print_m32r_misc_cpu;
183    }
184
185  /* Store in a global so things like sparc32_dump_regs can be invoked
186     from the gdb command line.  */
187  current_state = sd;
188
189  return sd;
190}
191
192void
193sim_close (sd, quitting)
194     SIM_DESC sd;
195     int quitting;
196{
197  m32r_cgen_cpu_close (CPU_CPU_DESC (STATE_CPU (sd, 0)));
198  sim_module_uninstall (sd);
199}
200
201SIM_RC
202sim_create_inferior (sd, abfd, argv, envp)
203     SIM_DESC sd;
204     struct bfd *abfd;
205     char **argv;
206     char **envp;
207{
208  SIM_CPU *current_cpu = STATE_CPU (sd, 0);
209  SIM_ADDR addr;
210
211  if (abfd != NULL)
212    addr = bfd_get_start_address (abfd);
213  else
214    addr = 0;
215  sim_pc_set (current_cpu, addr);
216
217#ifdef M32R_LINUX
218  m32rbf_h_cr_set (current_cpu,
219                    m32r_decode_gdb_ctrl_regnum(SPI_REGNUM), 0x1f00000);
220  m32rbf_h_cr_set (current_cpu,
221                    m32r_decode_gdb_ctrl_regnum(SPU_REGNUM), 0x1f00000);
222#endif
223
224#if 0
225  STATE_ARGV (sd) = sim_copy_argv (argv);
226  STATE_ENVP (sd) = sim_copy_argv (envp);
227#endif
228
229  return SIM_RC_OK;
230}
231
232/* PROFILE_CPU_CALLBACK */
233
234static void
235print_m32r_misc_cpu (SIM_CPU *cpu, int verbose)
236{
237  SIM_DESC sd = CPU_STATE (cpu);
238  char buf[20];
239
240  if (CPU_PROFILE_FLAGS (cpu) [PROFILE_INSN_IDX])
241    {
242      sim_io_printf (sd, "Miscellaneous Statistics\n\n");
243      sim_io_printf (sd, "  %-*s %s\n\n",
244		     PROFILE_LABEL_WIDTH, "Fill nops:",
245		     sim_add_commas (buf, sizeof (buf),
246				     CPU_M32R_MISC_PROFILE (cpu)->fillnop_count));
247      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_m32rx)
248	sim_io_printf (sd, "  %-*s %s\n\n",
249		       PROFILE_LABEL_WIDTH, "Parallel insns:",
250		       sim_add_commas (buf, sizeof (buf),
251				       CPU_M32R_MISC_PROFILE (cpu)->parallel_count));
252      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_m32r2)
253	sim_io_printf (sd, "  %-*s %s\n\n",
254		       PROFILE_LABEL_WIDTH, "Parallel insns:",
255		       sim_add_commas (buf, sizeof (buf),
256				       CPU_M32R_MISC_PROFILE (cpu)->parallel_count));
257    }
258}
259
260void
261sim_do_command (sd, cmd)
262     SIM_DESC sd;
263     char *cmd;
264{
265  char **argv;
266
267  if (cmd == NULL)
268    return;
269
270  argv = buildargv (cmd);
271
272  if (argv[0] != NULL
273      && strcasecmp (argv[0], "info") == 0
274      && argv[1] != NULL
275      && strncasecmp (argv[1], "reg", 3) == 0)
276    {
277      SI val;
278
279      /* We only support printing bbpsw,bbpc here as there is no equivalent
280	 functionality in gdb.  */
281      if (argv[2] == NULL)
282	sim_io_eprintf (sd, "Missing register in `%s'\n", cmd);
283      else if (argv[3] != NULL)
284	sim_io_eprintf (sd, "Too many arguments in `%s'\n", cmd);
285      else if (strcasecmp (argv[2], "bbpsw") == 0)
286	{
287	  val = m32rbf_h_cr_get (STATE_CPU (sd, 0), H_CR_BBPSW);
288	  sim_io_printf (sd, "bbpsw 0x%x %d\n", val, val);
289	}
290      else if (strcasecmp (argv[2], "bbpc") == 0)
291	{
292	  val = m32rbf_h_cr_get (STATE_CPU (sd, 0), H_CR_BBPC);
293	  sim_io_printf (sd, "bbpc 0x%x %d\n", val, val);
294	}
295      else
296	sim_io_eprintf (sd, "Printing of register `%s' not supported with `sim info'\n",
297			argv[2]);
298    }
299  else
300    {
301      if (sim_args_command (sd, cmd) != SIM_RC_OK)
302	sim_io_eprintf (sd, "Unknown sim command `%s'\n", cmd);
303    }
304
305  freeargv (argv);
306}
307