]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/m68hc11/interp.c
New simulator.
[thirdparty/binutils-gdb.git] / sim / m68hc11 / interp.c
CommitLineData
e0709f50
AC
1/* interp.c -- Simulator for Motorola 68HC11
2 Copyright (C) 1999, 2000 Free Software Foundation, Inc.
3 Written by Stephane Carrez (stcarrez@worldnet.fr)
4
5This file is part of GDB, the GNU debugger.
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 2, or (at your option)
10any 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 along
18with this program; if not, write to the Free Software Foundation, Inc.,
1959 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21#include "sim-main.h"
22#include "sim-assert.h"
23#include "sim-hw.h"
24#include "sim-options.h"
25#include "hw-tree.h"
26#include "hw-device.h"
27#include "hw-ports.h"
28
29#ifndef MONITOR_BASE
30# define MONITOR_BASE (0x0C000)
31# define MONITOR_SIZE (0x04000)
32#endif
33
34static void sim_get_info (SIM_DESC sd, char *cmd);
35
36
37char *interrupt_names[] = {
38 "reset",
39 "nmi",
40 "int",
41 NULL
42};
43
44#ifndef INLINE
45#if defined(__GNUC__) && defined(__OPTIMIZE__)
46#define INLINE __inline__
47#else
48#define INLINE
49#endif
50#endif
51
52struct sim_info_list
53{
54 const char *name;
55 const char *device;
56};
57
58struct sim_info_list dev_list[] = {
59 {"cpu", "/m68hc11"},
60 {"timer", "/m68hc11/m68hc11tim"},
61 {"sio", "/m68hc11/m68hc11sio"},
62 {"spi", "/m68hc11/m68hc11spi"},
63 {"eeprom", "/m68hc11/m68hc11eepr"},
64 {0, 0}
65};
66
67/* Give some information about the simulator. */
68static void
69sim_get_info (SIM_DESC sd, char *cmd)
70{
71 sim_cpu *cpu;
72
73 if (cmd != 0 && (cmd[0] == ' ' || cmd[0] == '-'))
74 {
75 int i;
76 struct hw *hw_dev;
77 cmd++;
78
79 for (i = 0; dev_list[i].name; i++)
80 if (strcmp (cmd, dev_list[i].name) == 0)
81 break;
82
83 if (dev_list[i].name == 0)
84 {
85 sim_io_eprintf (sd, "Device '%s' not found.\n", cmd);
86 sim_io_eprintf (sd, "Valid devices: cpu timer sio eeprom\n");
87 return;
88 }
89 hw_dev = sim_hw_parse (sd, dev_list[i].device);
90 if (hw_dev == 0)
91 {
92 sim_io_eprintf (sd, "Device '%s' not found\n", dev_list[i].device);
93 return;
94 }
95 hw_ioctl (hw_dev, 23, 0);
96 return;
97 }
98
99 cpu = STATE_CPU (sd, 0);
100 cpu_info (sd, cpu);
101 interrupts_info (sd, &cpu->cpu_interrupts);
102}
103
104
105void
106sim_board_reset (SIM_DESC sd)
107{
108 struct hw *hw_cpu;
109 sim_cpu *cpu;
110
111 cpu = STATE_CPU (sd, 0);
112 /* hw_cpu = sim_hw_parse (sd, "/"); */
113 hw_cpu = sim_hw_parse (sd, "/m68hc11");
114 if (hw_cpu == 0)
115 {
116 sim_io_eprintf (sd, "m68hc11 cpu not found in device tree.");
117 return;
118 }
119
120 cpu_reset (cpu);
121 hw_port_event (hw_cpu, 3, 0);
122 cpu_restart (cpu);
123}
124
125SIM_DESC
126sim_open (SIM_OPEN_KIND kind, host_callback *callback,
127 struct _bfd *abfd, char **argv)
128{
129 char **p;
130 SIM_DESC sd;
131 sim_cpu *cpu;
132 struct hw *device_tree;
133
134 sd = sim_state_alloc (kind, callback);
135 cpu = STATE_CPU (sd, 0);
136
137 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
138
139 /* for compatibility */
140 current_alignment = NONSTRICT_ALIGNMENT;
141 current_target_byte_order = BIG_ENDIAN;
142
143 cpu_initialize (sd, cpu);
144
145 cpu->cpu_use_elf_start = 1;
146 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
147 return 0;
148
149 /* getopt will print the error message so we just have to exit if this fails.
150 FIXME: Hmmm... in the case of gdb we need getopt to call
151 print_filtered. */
152 if (sim_parse_args (sd, argv) != SIM_RC_OK)
153 {
154 /* Uninstall the modules to avoid memory leaks,
155 file descriptor leaks, etc. */
156 sim_module_uninstall (sd);
157 return 0;
158 }
159
160 device_tree = sim_hw_parse (sd, "/");
161 if (hw_tree_find_property (device_tree, "/m68hc11/reg") == 0)
162 {
163 /* Allocate core managed memory */
164
165 /* the monitor */
166 sim_do_commandf (sd, "memory region 0x%lx,0x%lx",
167 /* MONITOR_BASE, MONITOR_SIZE */
168 0x8000, 0x8000);
169 sim_do_command (sd, " memory region 0x000,0x8000");
170 sim_hw_parse (sd, "/m68hc11/reg 0x1000 0x03F");
171 }
172
173 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11sio/reg") == 0)
174 {
175 sim_hw_parse (sd, "/m68hc11/m68hc11sio/reg 0x2b 0x5");
176 sim_hw_parse (sd, "/m68hc11/m68hc11sio/backend stdio");
177 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11sio");
178 }
179 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11tim/reg") == 0)
180 {
181 /* M68hc11 Timer configuration. */
182 sim_hw_parse (sd, "/m68hc11/m68hc11tim/reg 0x1b 0x5");
183 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11tim");
184 }
185
186 /* Create the SPI device. */
187 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11spi/reg") == 0)
188 {
189 sim_hw_parse (sd, "/m68hc11/m68hc11spi/reg 0x28 0x3");
190 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11spi");
191 }
192 if (hw_tree_find_property (device_tree, "/m68hc11/pram/reg") == 0)
193 {
194 /* M68hc11 persistent ram configuration. */
195 sim_hw_parse (sd, "/m68hc11/nvram/reg 0x0 256");
196 sim_hw_parse (sd, "/m68hc11/nvram/file m68hc11.ram");
197 sim_hw_parse (sd, "/m68hc11/nvram/mode save-modified");
198 sim_hw_parse (sd, "/m68hc11/nvram/overlap? true");
199 /*sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/pram"); */
200 }
201 if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11eepr/reg") == 0)
202 {
203 sim_hw_parse (sd, "/m68hc11/m68hc11eepr/reg 0xb000 512");
204 /* Connect the CPU reset to all devices. */
205 sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11eepr");
206 }
207
208 /* Check for/establish the a reference program image. */
209 if (sim_analyze_program (sd,
210 (STATE_PROG_ARGV (sd) != NULL
211 ? *STATE_PROG_ARGV (sd)
212 : NULL), abfd) != SIM_RC_OK)
213 {
214 sim_module_uninstall (sd);
215 return 0;
216 }
217
218 /* Establish any remaining configuration options. */
219 if (sim_config (sd) != SIM_RC_OK)
220 {
221 sim_module_uninstall (sd);
222 return 0;
223 }
224
225 if (sim_post_argv_init (sd) != SIM_RC_OK)
226 {
227 /* Uninstall the modules to avoid memory leaks,
228 file descriptor leaks, etc. */
229 sim_module_uninstall (sd);
230 return 0;
231 }
232
233 if (abfd != NULL)
234 {
235 cpu->cpu_elf_start = bfd_get_start_address (abfd);
236 }
237
238 sim_board_reset (sd);
239
240 /* Fudge our descriptor. */
241 return sd;
242}
243
244
245void
246sim_close (SIM_DESC sd, int quitting)
247{
248 /* shut down modules */
249 sim_module_uninstall (sd);
250
251 /* Ensure that any resources allocated through the callback
252 mechanism are released: */
253 sim_io_shutdown (sd);
254
255 /* FIXME - free SD */
256
257 return;
258}
259
260void
261sim_set_profile (int n)
262{
263}
264
265void
266sim_set_profile_size (int n)
267{
268}
269
270/* Generic implementation of sim_engine_run that works within the
271 sim_engine setjmp/longjmp framework. */
272
273void
274sim_engine_run (SIM_DESC sd,
275 int next_cpu_nr, /* ignore */
276 int nr_cpus, /* ignore */
277 int siggnal) /* ignore */
278{
279 sim_cpu *cpu;
280
281 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
282 cpu = STATE_CPU (sd, 0);
283 while (1)
284 {
285 cpu_single_step (cpu);
286
287 /* process any events */
288 if (sim_events_tickn (sd, cpu->cpu_current_cycle))
289 {
290 sim_events_process (sd);
291 }
292 }
293}
294
295int
296sim_trace (SIM_DESC sd)
297{
298 sim_resume (sd, 0, 0);
299 return 1;
300}
301
302void
303sim_info (SIM_DESC sd, int verbose)
304{
305 sim_io_eprintf (sd, "Simulator info:\n");
306 sim_io_eprintf (sd, " CPU Motorola 68HC11\n");
307 sim_get_info (sd, 0);
308 sim_module_info (sd, verbose || STATE_VERBOSE_P (sd));
309}
310
311SIM_RC
312sim_create_inferior (SIM_DESC sd, struct _bfd *abfd,
313 char **argv, char **env)
314{
315 sim_cpu *cpu;
316 int i;
317
318 cpu = STATE_CPU (sd, 0);
319
320 if (abfd != NULL)
321 {
322 cpu->cpu_elf_start = bfd_get_start_address (abfd);
323 }
324
325 /* reset all state information */
326 sim_board_reset (sd);
327
328 /* Get information about the number of pseudo registers. */
329 for (i = FIRST_SOFT_REGNUM; i <= ZD32_REGNUM; i++)
330 {
331 switch (i)
332 {
333 case TMP_REGNUM:
334 cpu->cpu_page0_reg[i - FIRST_SOFT_REGNUM] = 0;
335 break;
336 case Z_REGNUM:
337 case ZS_REGNUM:
338 cpu->cpu_page0_reg[i - FIRST_SOFT_REGNUM] = 2;
339 break;
340 case XY_REGNUM:
341 cpu->cpu_page0_reg[i - FIRST_SOFT_REGNUM] = 4;
342 break;
343 case FP_REGNUM:
344 cpu->cpu_page0_reg[i - FIRST_SOFT_REGNUM] = 6;
345 break;
346 default:
347 cpu->cpu_page0_reg[i - FIRST_SOFT_REGNUM]
348 = ((i - FIRST_SOFT_REGNUM) * 2) - 2;
349 break;
350 }
351 }
352 cpu->cpu_nb_pseudo_regs = 8;
353
354 return SIM_RC_OK;
355}
356
357
358void
359sim_set_callbacks (host_callback *p)
360{
361 /* m6811_callback = p; */
362}
363
364
365int
366sim_fetch_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
367{
368 sim_cpu *cpu;
369 uint16 val;
370
371 cpu = STATE_CPU (sd, 0);
372 switch (rn)
373 {
374 case A_REGNUM:
375 val = cpu_get_a (cpu);
376 break;
377
378 case B_REGNUM:
379 val = cpu_get_b (cpu);
380 break;
381
382 case D_REGNUM:
383 val = cpu_get_d (cpu);
384 break;
385
386 case X_REGNUM:
387 val = cpu_get_x (cpu);
388 break;
389
390 case Y_REGNUM:
391 val = cpu_get_y (cpu);
392 break;
393
394 case SP_REGNUM:
395 val = cpu_get_sp (cpu);
396 break;
397
398 case PC_REGNUM:
399 val = cpu_get_pc (cpu);
400 break;
401
402 case PSW_REGNUM:
403 val = cpu_get_ccr (cpu);
404 break;
405
406
407 /* Read a pseudo register. Pseudo registers are located at
408 beginning of page 0. Each of them is 2 bytes. */
409 default:
410 if (rn < FIRST_SOFT_REGNUM || rn >= ZD32_REGNUM)
411 {
412 val = 0;
413 }
414 else
415 {
416 uint16 addr;
417
418 addr = cpu->cpu_page0_reg[rn - FIRST_SOFT_REGNUM];
419 val = memory_read16 (cpu, addr);
420 }
421 break;
422 }
423 memory[0] = val >> 8;
424 memory[1] = val & 0x0FF;
425 return 2;
426}
427
428int
429sim_store_register (SIM_DESC sd, int rn, unsigned char *memory, int length)
430{
431 uint16 val;
432 sim_cpu *cpu;
433
434 cpu = STATE_CPU (sd, 0);
435
436 val = *memory++;
437 if (length == 2)
438 val = (val << 8) | *memory;
439
440 switch (rn)
441 {
442 case D_REGNUM:
443 cpu_set_d (cpu, val);
444 break;
445
446 case A_REGNUM:
447 cpu_set_a (cpu, val);
448 break;
449
450 case B_REGNUM:
451 cpu_set_b (cpu, val);
452 break;
453
454 case X_REGNUM:
455 cpu_set_x (cpu, val);
456 break;
457
458 case Y_REGNUM:
459 cpu_set_y (cpu, val);
460 break;
461
462 case SP_REGNUM:
463 cpu_set_sp (cpu, val);
464 break;
465
466 case PC_REGNUM:
467 cpu_set_pc (cpu, val);
468 break;
469
470 case PSW_REGNUM:
471 cpu_set_ccr (cpu, val);
472 break;
473
474 /* Write a pseudo register. Pseudo registers are located at
475 beginning of page 0. Each of them is 2 bytes. */
476 default:
477 if (rn >= FIRST_SOFT_REGNUM && rn <= ZD32_REGNUM)
478 {
479 uint16 addr;
480
481 addr = cpu->cpu_page0_reg[rn - FIRST_SOFT_REGNUM];
482 memory_write16 (cpu, addr, val);
483 }
484 break;
485 }
486
487 return 2;
488}
489
490void
491sim_size (int s)
492{
493 ;
494}
495
496void
497sim_do_command (SIM_DESC sd, char *cmd)
498{
499 char *mm_cmd = "memory-map";
500 char *int_cmd = "interrupt";
501
502 /* Commands available from GDB: */
503 if (sim_args_command (sd, cmd) != SIM_RC_OK)
504 {
505 if (strncmp (cmd, "info", sizeof ("info") - 1) == 0)
506 sim_get_info (sd, &cmd[4]);
507 else if (strncmp (cmd, "frame", sizeof ("frame") - 1) == 0)
508 cpu_print_frame (sd, STATE_CPU (sd, 0));
509 else if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0))
510 sim_io_eprintf (sd,
511 "`memory-map' command replaced by `sim memory'\n");
512 else if (strncmp (cmd, int_cmd, strlen (int_cmd)) == 0)
513 sim_io_eprintf (sd, "`interrupt' command replaced by `sim watch'\n");
514 else
515 sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
516 }
517}