1/* Main simulator entry points specific to the FRV.
2   Copyright (C) 1998, 1999, 2000, 2007 Free Software Foundation, Inc.
3   Contributed by Red Hat.
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
9the Free Software Foundation; either version 3 of the License, or
10(at your option) any later version.
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
17You should have received a copy of the GNU General Public License
18along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20#define WANT_CPU
21#define WANT_CPU_FRVBF
22#include "sim-main.h"
23#ifdef HAVE_STDLIB_H
24#include <stdlib.h>
25#endif
26#include "sim-options.h"
27#include "libiberty.h"
28#include "bfd.h"
29#include "elf-bfd.h"
30
31static void free_state (SIM_DESC);
32static void print_frv_misc_cpu (SIM_CPU *cpu, int verbose);
33
34/* Records simulator descriptor so utilities like frv_dump_regs can be
35   called from gdb.  */
36SIM_DESC current_state;
37
38/* Cover function of sim_state_free to free the cpu buffers as well.  */
39
40static void
41free_state (SIM_DESC sd)
42{
43  if (STATE_MODULES (sd) != NULL)
44    sim_module_uninstall (sd);
45  sim_cpu_free_all (sd);
46  sim_state_free (sd);
47}
48
49/* Create an instance of the simulator.  */
50
51SIM_DESC
52sim_open (kind, callback, abfd, argv)
53     SIM_OPEN_KIND kind;
54     host_callback *callback;
55     bfd *abfd;
56     char **argv;
57{
58  char c;
59  int i;
60  unsigned long elf_flags = 0;
61  SIM_DESC sd = sim_state_alloc (kind, callback);
62
63  /* The cpu data is kept in a separately allocated chunk of memory.  */
64  if (sim_cpu_alloc_all (sd, 1, cgen_cpu_max_extra_bytes ()) != SIM_RC_OK)
65    {
66      free_state (sd);
67      return 0;
68    }
69
70#if 0 /* FIXME: pc is in mach-specific struct */
71  /* FIXME: watchpoints code shouldn't need this */
72  {
73    SIM_CPU *current_cpu = STATE_CPU (sd, 0);
74    STATE_WATCHPOINTS (sd)->pc = &(PC);
75    STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
76  }
77#endif
78
79  if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
80    {
81      free_state (sd);
82      return 0;
83    }
84
85  /* These options override any module options.
86     Obviously ambiguity should be avoided, however the caller may wish to
87     augment the meaning of an option.  */
88  sim_add_option_table (sd, NULL, frv_options);
89
90  /* getopt will print the error message so we just have to exit if this fails.
91     FIXME: Hmmm...  in the case of gdb we need getopt to call
92     print_filtered.  */
93  if (sim_parse_args (sd, argv) != SIM_RC_OK)
94    {
95      free_state (sd);
96      return 0;
97    }
98
99#if 0
100  /* Allocate a handler for the control registers and other devices
101     if no memory for that range has been allocated by the user.
102     All are allocated in one chunk to keep things from being
103     unnecessarily complicated.  */
104  if (sim_core_read_buffer (sd, NULL, read_map, &c, FRV_DEVICE_ADDR, 1) == 0)
105    sim_core_attach (sd, NULL,
106		     0 /*level*/,
107		     access_read_write,
108		     0 /*space ???*/,
109		     FRV_DEVICE_ADDR, FRV_DEVICE_LEN /*nr_bytes*/,
110		     0 /*modulo*/,
111		     &frv_devices,
112		     NULL /*buffer*/);
113#endif
114
115  /* Allocate core managed memory if none specified by user.
116     Use address 4 here in case the user wanted address 0 unmapped.  */
117  if (sim_core_read_buffer (sd, NULL, read_map, &c, 4, 1) == 0)
118    sim_do_commandf (sd, "memory region 0,0x%lx", FRV_DEFAULT_MEM_SIZE);
119
120  /* check for/establish the reference program image */
121  if (sim_analyze_program (sd,
122			   (STATE_PROG_ARGV (sd) != NULL
123			    ? *STATE_PROG_ARGV (sd)
124			    : NULL),
125			   abfd) != SIM_RC_OK)
126    {
127      free_state (sd);
128      return 0;
129    }
130
131  /* set machine and architecture correctly instead of defaulting to frv */
132  {
133    bfd *prog_bfd = STATE_PROG_BFD (sd);
134    if (prog_bfd != NULL)
135      {
136	struct elf_backend_data *backend_data;
137
138	if (bfd_get_arch (prog_bfd) != bfd_arch_frv)
139	  {
140	    sim_io_eprintf (sd, "%s: \"%s\" is not a FRV object file\n",
141			    STATE_MY_NAME (sd),
142			    bfd_get_filename (prog_bfd));
143	    free_state (sd);
144	    return 0;
145	  }
146
147	backend_data = get_elf_backend_data (prog_bfd);
148
149	if (backend_data != NULL)
150	  backend_data->elf_backend_object_p (prog_bfd);
151
152	elf_flags = elf_elfheader (prog_bfd)->e_flags;
153      }
154  }
155
156  /* Establish any remaining configuration options.  */
157  if (sim_config (sd) != SIM_RC_OK)
158    {
159      free_state (sd);
160      return 0;
161    }
162
163  if (sim_post_argv_init (sd) != SIM_RC_OK)
164    {
165      free_state (sd);
166      return 0;
167    }
168
169  /* Open a copy of the cpu descriptor table.  */
170  {
171    CGEN_CPU_DESC cd = frv_cgen_cpu_open_1 (STATE_ARCHITECTURE (sd)->printable_name,
172					     CGEN_ENDIAN_BIG);
173    for (i = 0; i < MAX_NR_PROCESSORS; ++i)
174      {
175	SIM_CPU *cpu = STATE_CPU (sd, i);
176	CPU_CPU_DESC (cpu) = cd;
177	CPU_DISASSEMBLER (cpu) = sim_cgen_disassemble_insn;
178	CPU_ELF_FLAGS (cpu) = elf_flags;
179      }
180    frv_cgen_init_dis (cd);
181  }
182
183  /* Initialize various cgen things not done by common framework.
184     Must be done after frv_cgen_cpu_open.  */
185  cgen_init (sd);
186
187  /* CPU specific initialization.  */
188  for (i = 0; i < MAX_NR_PROCESSORS; ++i)
189    {
190      SIM_CPU* cpu = STATE_CPU (sd, i);
191      frv_initialize (cpu, sd);
192    }
193
194  /* Store in a global so things like sparc32_dump_regs can be invoked
195     from the gdb command line.  */
196  current_state = sd;
197
198  return sd;
199}
200
201void
202sim_close (sd, quitting)
203     SIM_DESC sd;
204     int quitting;
205{
206  int i;
207  /* Terminate cache support.  */
208  for (i = 0; i < MAX_NR_PROCESSORS; ++i)
209    {
210      SIM_CPU* cpu = STATE_CPU (sd, i);
211      frv_cache_term (CPU_INSN_CACHE (cpu));
212      frv_cache_term (CPU_DATA_CACHE (cpu));
213    }
214
215  frv_cgen_cpu_close (CPU_CPU_DESC (STATE_CPU (sd, 0)));
216  sim_module_uninstall (sd);
217}
218
219SIM_RC
220sim_create_inferior (sd, abfd, argv, envp)
221     SIM_DESC sd;
222     bfd *abfd;
223     char **argv;
224     char **envp;
225{
226  SIM_CPU *current_cpu = STATE_CPU (sd, 0);
227  SIM_ADDR addr;
228
229  if (abfd != NULL)
230    addr = bfd_get_start_address (abfd);
231  else
232    addr = 0;
233  sim_pc_set (current_cpu, addr);
234
235#if 0
236  STATE_ARGV (sd) = sim_copy_argv (argv);
237  STATE_ENVP (sd) = sim_copy_argv (envp);
238#endif
239
240  return SIM_RC_OK;
241}
242
243void
244sim_do_command (sd, cmd)
245     SIM_DESC sd;
246     char *cmd;
247{
248  if (sim_args_command (sd, cmd) != SIM_RC_OK)
249    sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
250}
251