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