1 /* Main simulator entry points for the i960.
2 Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
3 Contributed by Cygnus Support.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18
19 #include "libiberty.h"
20 #include "bfd.h"
21 #include "sim-main.h"
22 #ifdef HAVE_STDLIB_H
23 #include <stdlib.h>
24 #endif
25 #include "sim-options.h"
26 #include "dis-asm.h"
27
28 static void free_state (SIM_DESC);
29
30 /* Since we don't build the cgen-opcode table, we use the old
31 disassembler. */
32 static CGEN_DISASSEMBLER i960_disassemble_insn;
33
34 /* Records simulator descriptor so utilities like i960_dump_regs can be
35 called from gdb. */
36 SIM_DESC current_state;
37
38 /* Cover function of sim_state_free to free the cpu buffers as well. */
39
40 static void
free_state(SIM_DESC sd)41 free_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
51 SIM_DESC
sim_open(kind,callback,abfd,argv)52 sim_open (kind, callback, abfd, argv)
53 SIM_OPEN_KIND kind;
54 host_callback *callback;
55 struct bfd *abfd;
56 char **argv;
57 {
58 char c;
59 int i;
60 SIM_DESC sd = sim_state_alloc (kind, callback);
61
62 /* The cpu data is kept in a separately allocated chunk of memory. */
63 if (sim_cpu_alloc_all (sd, 1, cgen_cpu_max_extra_bytes ()) != SIM_RC_OK)
64 {
65 free_state (sd);
66 return 0;
67 }
68
69 #if 0 /* FIXME: pc is in mach-specific struct */
70 /* FIXME: watchpoints code shouldn't need this */
71 {
72 SIM_CPU *current_cpu = STATE_CPU (sd, 0);
73 STATE_WATCHPOINTS (sd)->pc = &(PC);
74 STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
75 }
76 #endif
77
78 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
79 {
80 free_state (sd);
81 return 0;
82 }
83
84 #if 0 /* FIXME: 'twould be nice if we could do this */
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 if (extra_options != NULL)
89 sim_add_option_table (sd, extra_options);
90 #endif
91
92 /* getopt will print the error message so we just have to exit if this fails.
93 FIXME: Hmmm... in the case of gdb we need getopt to call
94 print_filtered. */
95 if (sim_parse_args (sd, argv) != SIM_RC_OK)
96 {
97 free_state (sd);
98 return 0;
99 }
100
101 /* Allocate a handler for the control registers and other devices
102 if no memory for that range has been allocated by the user.
103 All are allocated in one chunk to keep things from being
104 unnecessarily complicated. */
105 if (sim_core_read_buffer (sd, NULL, read_map, &c, I960_DEVICE_ADDR, 1) == 0)
106 sim_core_attach (sd, NULL,
107 0 /*level*/,
108 access_read_write,
109 0 /*space ???*/,
110 I960_DEVICE_ADDR, I960_DEVICE_LEN /*nr_bytes*/,
111 0 /*modulo*/,
112 &i960_devices,
113 NULL /*buffer*/);
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 /* ??? wilson */
119 sim_do_commandf (sd, "memory region 0x%lx,0x%lx", I960_DEFAULT_MEM_START,
120 I960_DEFAULT_MEM_SIZE);
121
122 /* check for/establish the reference program image */
123 if (sim_analyze_program (sd,
124 (STATE_PROG_ARGV (sd) != NULL
125 ? *STATE_PROG_ARGV (sd)
126 : NULL),
127 abfd) != SIM_RC_OK)
128 {
129 free_state (sd);
130 return 0;
131 }
132
133 /* Establish any remaining configuration options. */
134 if (sim_config (sd) != SIM_RC_OK)
135 {
136 free_state (sd);
137 return 0;
138 }
139
140 if (sim_post_argv_init (sd) != SIM_RC_OK)
141 {
142 free_state (sd);
143 return 0;
144 }
145
146 /* Open a copy of the cpu descriptor table. */
147 {
148 CGEN_CPU_DESC cd = i960_cgen_cpu_open_1 (STATE_ARCHITECTURE (sd)->printable_name,
149 CGEN_ENDIAN_LITTLE);
150 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
151 {
152 SIM_CPU *cpu = STATE_CPU (sd, i);
153 CPU_CPU_DESC (cpu) = cd;
154 CPU_DISASSEMBLER (cpu) = i960_disassemble_insn;
155 }
156 }
157
158 /* Initialize various cgen things not done by common framework.
159 Must be done after i960_cgen_cpu_open. */
160 cgen_init (sd);
161
162 /* Store in a global so things like i960_dump_regs can be invoked
163 from the gdb command line. */
164 current_state = sd;
165
166 return sd;
167 }
168
169 void
sim_close(sd,quitting)170 sim_close (sd, quitting)
171 SIM_DESC sd;
172 int quitting;
173 {
174 i960_cgen_cpu_close (CPU_CPU_DESC (STATE_CPU (sd, 0)));
175 sim_module_uninstall (sd);
176 }
177
178 SIM_RC
sim_create_inferior(sd,abfd,argv,envp)179 sim_create_inferior (sd, abfd, argv, envp)
180 SIM_DESC sd;
181 struct bfd *abfd;
182 char **argv;
183 char **envp;
184 {
185 SIM_CPU *current_cpu = STATE_CPU (sd, 0);
186 SIM_ADDR addr;
187
188 if (abfd != NULL)
189 addr = bfd_get_start_address (abfd);
190 else
191 addr = 0;
192 sim_pc_set (current_cpu, addr);
193
194 #if 0
195 STATE_ARGV (sd) = sim_copy_argv (argv);
196 STATE_ENVP (sd) = sim_copy_argv (envp);
197 #endif
198
199 return SIM_RC_OK;
200 }
201
202 #if 0
203 int
204 sim_stop (SIM_DESC sd)
205 {
206 switch (STATE_ARCHITECTURE (sd)->mach)
207 {
208 case bfd_mach_i960_ka_sa :
209 return i960base_engine_stop (sd, NULL, NULL_CIA, sim_stopped, SIM_SIGINT);
210 default :
211 abort ();
212 }
213 }
214
215 /* This isn't part of the official interface.
216 This is just a good place to put this for now. */
217
218 void
219 sim_sync_stop (SIM_DESC sd, SIM_CPU *cpu, PCADDR pc, enum sim_stop reason, int sigrc)
220 {
221 switch (STATE_ARCHITECTURE (sd)->mach)
222 {
223 case bfd_mach_i960_ka_sa :
224 (void) i960base_engine_stop (sd, cpu, pc, reason, sigrc);
225 break;
226 default :
227 abort ();
228 }
229 }
230
231 void
232 sim_resume (sd, step, siggnal)
233 SIM_DESC sd;
234 int step, siggnal;
235 {
236 sim_module_resume (sd);
237
238 switch (STATE_ARCHITECTURE (sd)->mach)
239 {
240 case bfd_mach_i960_ka_sa :
241 i960base_engine_run (sd, step, siggnal);
242 break;
243 default :
244 abort ();
245 }
246
247 sim_module_suspend (sd);
248 }
249 #endif
250
251 /* The contents of BUF are in target byte order. */
252
253 int
sim_fetch_register(sd,rn,buf,length)254 sim_fetch_register (sd, rn, buf, length)
255 SIM_DESC sd;
256 int rn;
257 unsigned char *buf;
258 int length;
259 {
260 SIM_CPU *cpu = STATE_CPU (sd, 0);
261
262 return (* CPU_REG_FETCH (cpu)) (cpu, rn, buf, length);
263 }
264
265 /* The contents of BUF are in target byte order. */
266
267 int
sim_store_register(sd,rn,buf,length)268 sim_store_register (sd, rn, buf, length)
269 SIM_DESC sd;
270 int rn;
271 unsigned char *buf;
272 int length;
273 {
274 SIM_CPU *cpu = STATE_CPU (sd, 0);
275
276 return (* CPU_REG_STORE (cpu)) (cpu, rn, buf, length);
277 }
278
279 void
sim_do_command(sd,cmd)280 sim_do_command (sd, cmd)
281 SIM_DESC sd;
282 char *cmd;
283 {
284 if (sim_args_command (sd, cmd) != SIM_RC_OK)
285 sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
286 }
287
288 /* Disassemble an instruction. */
289
290 static void
i960_disassemble_insn(SIM_CPU * cpu,const CGEN_INSN * insn,const ARGBUF * abuf,IADDR pc,char * buf)291 i960_disassemble_insn (SIM_CPU *cpu, const CGEN_INSN *insn,
292 const ARGBUF *abuf, IADDR pc, char *buf)
293 {
294 struct disassemble_info disasm_info;
295 SFILE sfile;
296 SIM_DESC sd = CPU_STATE (cpu);
297 int insn_length = CGEN_INSN_BITSIZE (insn) / 8;
298
299 sfile.buffer = sfile.current = buf;
300 INIT_DISASSEMBLE_INFO (disasm_info, (FILE *) &sfile,
301 (fprintf_ftype) sim_disasm_sprintf);
302 disasm_info.endian =
303 (bfd_big_endian (STATE_PROG_BFD (sd)) ? BFD_ENDIAN_BIG
304 : bfd_little_endian (STATE_PROG_BFD (sd)) ? BFD_ENDIAN_LITTLE
305 : BFD_ENDIAN_UNKNOWN);
306 disasm_info.read_memory_func = sim_disasm_read_memory;
307 disasm_info.memory_error_func = sim_disasm_perror_memory;
308 disasm_info.application_data = (PTR) cpu;
309
310 print_insn_i960 (pc, &disasm_info);
311 }
312