]> Git Repo - binutils.git/blob - sim/m68hc11/interp.c
sim: switch config.h usage to defs.h
[binutils.git] / sim / m68hc11 / interp.c
1 /* interp.c -- Simulator for Motorola 68HC11/68HC12
2    Copyright (C) 1999-2021 Free Software Foundation, Inc.
3    Written by Stephane Carrez ([email protected])
4
5 This file is part of GDB, the GNU debugger.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20 /* This must come before any other includes.  */
21 #include "defs.h"
22
23 #include "sim-main.h"
24 #include "sim-assert.h"
25 #include "sim-hw.h"
26 #include "sim-options.h"
27 #include "hw-tree.h"
28 #include "hw-device.h"
29 #include "hw-ports.h"
30 #include "elf32-m68hc1x.h"
31
32 #ifndef MONITOR_BASE
33 # define MONITOR_BASE (0x0C000)
34 # define MONITOR_SIZE (0x04000)
35 #endif
36
37 static void sim_get_info (SIM_DESC sd, char *cmd);
38
39 struct sim_info_list
40 {
41   const char *name;
42   const char *device;
43 };
44
45 struct sim_info_list dev_list_68hc11[] = {
46   {"cpu", "/m68hc11"},
47   {"timer", "/m68hc11/m68hc11tim"},
48   {"sio", "/m68hc11/m68hc11sio"},
49   {"spi", "/m68hc11/m68hc11spi"},
50   {"eeprom", "/m68hc11/m68hc11eepr"},
51   {0, 0}
52 };
53
54 struct sim_info_list dev_list_68hc12[] = {
55   {"cpu", "/m68hc12"},
56   {"timer", "/m68hc12/m68hc12tim"},
57   {"sio", "/m68hc12/m68hc12sio"},
58   {"spi", "/m68hc12/m68hc12spi"},
59   {"eeprom", "/m68hc12/m68hc12eepr"},
60   {0, 0}
61 };
62
63 /* Cover function of sim_state_free to free the cpu buffers as well.  */
64
65 static void
66 free_state (SIM_DESC sd)
67 {
68   if (STATE_MODULES (sd) != NULL)
69     sim_module_uninstall (sd);
70
71   sim_state_free (sd);
72 }
73
74 /* Give some information about the simulator.  */
75 static void
76 sim_get_info (SIM_DESC sd, char *cmd)
77 {
78   sim_cpu *cpu;
79
80   cpu = STATE_CPU (sd, 0);
81   if (cmd != 0 && (cmd[0] == ' ' || cmd[0] == '-'))
82     {
83       int i;
84       struct hw *hw_dev;
85       struct sim_info_list *dev_list;
86       const struct bfd_arch_info *arch;
87
88       arch = STATE_ARCHITECTURE (sd);
89       cmd++;
90
91       if (arch->arch == bfd_arch_m68hc11)
92         dev_list = dev_list_68hc11;
93       else
94         dev_list = dev_list_68hc12;
95
96       for (i = 0; dev_list[i].name; i++)
97         if (strcmp (cmd, dev_list[i].name) == 0)
98           break;
99
100       if (dev_list[i].name == 0)
101         {
102           sim_io_eprintf (sd, "Device '%s' not found.\n", cmd);
103           sim_io_eprintf (sd, "Valid devices: cpu timer sio eeprom\n");
104           return;
105         }
106       hw_dev = sim_hw_parse (sd, "%s", dev_list[i].device);
107       if (hw_dev == 0)
108         {
109           sim_io_eprintf (sd, "Device '%s' not found\n", dev_list[i].device);
110           return;
111         }
112       hw_ioctl (hw_dev, 23, 0);
113       return;
114     }
115
116   cpu_info (sd, cpu);
117   interrupts_info (sd, &cpu->cpu_interrupts);
118 }
119
120
121 void
122 sim_board_reset (SIM_DESC sd)
123 {
124   struct hw *hw_cpu;
125   sim_cpu *cpu;
126   const struct bfd_arch_info *arch;
127   const char *cpu_type;
128
129   cpu = STATE_CPU (sd, 0);
130   arch = STATE_ARCHITECTURE (sd);
131
132   /*  hw_cpu = sim_hw_parse (sd, "/"); */
133   if (arch->arch == bfd_arch_m68hc11)
134     {
135       cpu->cpu_type = CPU_M6811;
136       cpu_type = "/m68hc11";
137     }
138   else
139     {
140       cpu->cpu_type = CPU_M6812;
141       cpu_type = "/m68hc12";
142     }
143   
144   hw_cpu = sim_hw_parse (sd, "%s", cpu_type);
145   if (hw_cpu == 0)
146     {
147       sim_io_eprintf (sd, "%s cpu not found in device tree.", cpu_type);
148       return;
149     }
150
151   cpu_reset (cpu);
152   hw_port_event (hw_cpu, 3, 0);
153   cpu_restart (cpu);
154 }
155
156 static int
157 sim_hw_configure (SIM_DESC sd)
158 {
159   const struct bfd_arch_info *arch;
160   struct hw *device_tree;
161   sim_cpu *cpu;
162   
163   arch = STATE_ARCHITECTURE (sd);
164   if (arch == 0)
165     return 0;
166
167   cpu = STATE_CPU (sd, 0);
168   cpu->cpu_configured_arch = arch;
169   device_tree = sim_hw_parse (sd, "/");
170   if (arch->arch == bfd_arch_m68hc11)
171     {
172       cpu->cpu_interpretor = cpu_interp_m6811;
173       if (hw_tree_find_property (device_tree, "/m68hc11/reg") == 0)
174         {
175           /* Allocate core managed memory */
176
177           /* the monitor  */
178           sim_do_commandf (sd, "memory region 0x%x@%d,0x%x",
179                            /* MONITOR_BASE, MONITOR_SIZE */
180                            0x8000, M6811_RAM_LEVEL, 0x8000);
181           sim_do_commandf (sd, "memory region 0x000@%d,0x8000",
182                            M6811_RAM_LEVEL);
183           sim_hw_parse (sd, "/m68hc11/reg 0x1000 0x03F");
184           if (cpu->bank_start < cpu->bank_end)
185             {
186               sim_do_commandf (sd, "memory region 0x%x@%d,0x100000",
187                                cpu->bank_virtual, M6811_RAM_LEVEL);
188               sim_hw_parse (sd, "/m68hc11/use_bank 1");
189             }
190         }
191       if (cpu->cpu_start_mode)
192         {
193           sim_hw_parse (sd, "/m68hc11/mode %s", cpu->cpu_start_mode);
194         }
195       if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11sio/reg") == 0)
196         {
197           sim_hw_parse (sd, "/m68hc11/m68hc11sio/reg 0x2b 0x5");
198           sim_hw_parse (sd, "/m68hc11/m68hc11sio/backend stdio");
199           sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11sio");
200         }
201       if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11tim/reg") == 0)
202         {
203           /* M68hc11 Timer configuration. */
204           sim_hw_parse (sd, "/m68hc11/m68hc11tim/reg 0x1b 0x5");
205           sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11tim");
206           sim_hw_parse (sd, "/m68hc11 > capture capture /m68hc11/m68hc11tim");
207         }
208
209       /* Create the SPI device.  */
210       if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11spi/reg") == 0)
211         {
212           sim_hw_parse (sd, "/m68hc11/m68hc11spi/reg 0x28 0x3");
213           sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11spi");
214         }
215       if (hw_tree_find_property (device_tree, "/m68hc11/nvram/reg") == 0)
216         {
217           /* M68hc11 persistent ram configuration. */
218           sim_hw_parse (sd, "/m68hc11/nvram/reg 0x0 256");
219           sim_hw_parse (sd, "/m68hc11/nvram/file m68hc11.ram");
220           sim_hw_parse (sd, "/m68hc11/nvram/mode save-modified");
221           /*sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/pram"); */
222         }
223       if (hw_tree_find_property (device_tree, "/m68hc11/m68hc11eepr/reg") == 0)
224         {
225           sim_hw_parse (sd, "/m68hc11/m68hc11eepr/reg 0xb000 512");
226           sim_hw_parse (sd, "/m68hc11 > cpu-reset reset /m68hc11/m68hc11eepr");
227         }
228       sim_hw_parse (sd, "/m68hc11 > port-a cpu-write-port /m68hc11");
229       sim_hw_parse (sd, "/m68hc11 > port-b cpu-write-port /m68hc11");
230       sim_hw_parse (sd, "/m68hc11 > port-c cpu-write-port /m68hc11");
231       sim_hw_parse (sd, "/m68hc11 > port-d cpu-write-port /m68hc11");
232       cpu->hw_cpu = sim_hw_parse (sd, "/m68hc11");
233     }
234   else
235     {
236       cpu->cpu_interpretor = cpu_interp_m6812;
237       if (hw_tree_find_property (device_tree, "/m68hc12/reg") == 0)
238         {
239           /* Allocate core external memory.  */
240           sim_do_commandf (sd, "memory region 0x%x@%d,0x%x",
241                            0x8000, M6811_RAM_LEVEL, 0x8000);
242           sim_do_commandf (sd, "memory region 0x000@%d,0x8000",
243                            M6811_RAM_LEVEL);
244           if (cpu->bank_start < cpu->bank_end)
245             {
246               sim_do_commandf (sd, "memory region 0x%x@%d,0x100000",
247                                cpu->bank_virtual, M6811_RAM_LEVEL);
248               sim_hw_parse (sd, "/m68hc12/use_bank 1");
249             }
250           sim_hw_parse (sd, "/m68hc12/reg 0x0 0x3FF");
251         }
252
253       if (!hw_tree_find_property (device_tree, "/m68hc12/m68hc12sio@1/reg"))
254         {
255           sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/reg 0xC0 0x8");
256           sim_hw_parse (sd, "/m68hc12/m68hc12sio@1/backend stdio");
257           sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12sio@1");
258         }
259       if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12tim/reg") == 0)
260         {
261           /* M68hc11 Timer configuration. */
262           sim_hw_parse (sd, "/m68hc12/m68hc12tim/reg 0x1b 0x5");
263           sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12tim");
264           sim_hw_parse (sd, "/m68hc12 > capture capture /m68hc12/m68hc12tim");
265         }
266
267       /* Create the SPI device.  */
268       if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12spi/reg") == 0)
269         {
270           sim_hw_parse (sd, "/m68hc12/m68hc12spi/reg 0x28 0x3");
271           sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12spi");
272         }
273       if (hw_tree_find_property (device_tree, "/m68hc12/nvram/reg") == 0)
274         {
275           /* M68hc11 persistent ram configuration. */
276           sim_hw_parse (sd, "/m68hc12/nvram/reg 0x2000 8192");
277           sim_hw_parse (sd, "/m68hc12/nvram/file m68hc12.ram");
278           sim_hw_parse (sd, "/m68hc12/nvram/mode save-modified");
279         }
280       if (hw_tree_find_property (device_tree, "/m68hc12/m68hc12eepr/reg") == 0)
281         {
282           sim_hw_parse (sd, "/m68hc12/m68hc12eepr/reg 0x0800 2048");
283           sim_hw_parse (sd, "/m68hc12 > cpu-reset reset /m68hc12/m68hc12eepr");
284         }
285
286       sim_hw_parse (sd, "/m68hc12 > port-a cpu-write-port /m68hc12");
287       sim_hw_parse (sd, "/m68hc12 > port-b cpu-write-port /m68hc12");
288       sim_hw_parse (sd, "/m68hc12 > port-c cpu-write-port /m68hc12");
289       sim_hw_parse (sd, "/m68hc12 > port-d cpu-write-port /m68hc12");
290       cpu->hw_cpu = sim_hw_parse (sd, "/m68hc12");
291     }
292   return 1;
293 }
294
295 /* Get the memory bank parameters by looking at the global symbols
296    defined by the linker.  */
297 static int
298 sim_get_bank_parameters (SIM_DESC sd)
299 {
300   sim_cpu *cpu;
301   unsigned size;
302   bfd_vma addr;
303
304   cpu = STATE_CPU (sd, 0);
305
306   addr = trace_sym_value (sd, BFD_M68HC11_BANK_START_NAME);
307   if (addr != -1)
308     cpu->bank_start = addr;
309
310   size = trace_sym_value (sd, BFD_M68HC11_BANK_SIZE_NAME);
311   if (size == -1)
312     size = 0;
313
314   addr = trace_sym_value (sd, BFD_M68HC11_BANK_VIRTUAL_NAME);
315   if (addr != -1)
316     cpu->bank_virtual = addr;
317
318   cpu->bank_end = cpu->bank_start + size;
319   cpu->bank_shift = 0;
320   for (; size > 1; size >>= 1)
321     cpu->bank_shift++;
322
323   return 0;
324 }
325
326 static int
327 sim_prepare_for_program (SIM_DESC sd, bfd* abfd)
328 {
329   sim_cpu *cpu;
330   int elf_flags = 0;
331
332   cpu = STATE_CPU (sd, 0);
333
334   if (abfd != NULL)
335     {
336       asection *s;
337
338       if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
339         elf_flags = elf_elfheader (abfd)->e_flags;
340
341       cpu->cpu_elf_start = bfd_get_start_address (abfd);
342       /* See if any section sets the reset address */
343       cpu->cpu_use_elf_start = 1;
344       for (s = abfd->sections; s && cpu->cpu_use_elf_start; s = s->next) 
345         {
346           if (s->flags & SEC_LOAD)
347             {
348               bfd_size_type size;
349
350               size = bfd_section_size (s);
351               if (size > 0)
352                 {
353                   bfd_vma lma;
354
355                   if (STATE_LOAD_AT_LMA_P (sd))
356                     lma = bfd_section_lma (s);
357                   else
358                     lma = bfd_section_vma (s);
359
360                   if (lma <= 0xFFFE && lma+size >= 0x10000)
361                     cpu->cpu_use_elf_start = 0;
362                 }
363             }
364         }
365
366       if (elf_flags & E_M68HC12_BANKS)
367         {
368           if (sim_get_bank_parameters (sd) != 0)
369             sim_io_eprintf (sd, "Memory bank parameters are not initialized\n");
370         }
371     }
372
373   if (!sim_hw_configure (sd))
374     return SIM_RC_FAIL;
375
376   /* reset all state information */
377   sim_board_reset (sd);
378
379   return SIM_RC_OK;
380 }
381
382 static sim_cia
383 m68hc11_pc_get (sim_cpu *cpu)
384 {
385   return cpu_get_pc (cpu);
386 }
387
388 static void
389 m68hc11_pc_set (sim_cpu *cpu, sim_cia pc)
390 {
391   cpu_set_pc (cpu, pc);
392 }
393
394 static int m68hc11_reg_fetch (SIM_CPU *, int, unsigned char *, int);
395 static int m68hc11_reg_store (SIM_CPU *, int, unsigned char *, int);
396
397 SIM_DESC
398 sim_open (SIM_OPEN_KIND kind, host_callback *callback,
399           bfd *abfd, char * const *argv)
400 {
401   int i;
402   SIM_DESC sd;
403   sim_cpu *cpu;
404
405   sd = sim_state_alloc (kind, callback);
406
407   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
408
409   /* The cpu data is kept in a separately allocated chunk of memory.  */
410   if (sim_cpu_alloc_all (sd, 1) != SIM_RC_OK)
411     {
412       free_state (sd);
413       return 0;
414     }
415
416   cpu = STATE_CPU (sd, 0);
417
418   cpu_initialize (sd, cpu);
419
420   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
421     {
422       free_state (sd);
423       return 0;
424     }
425
426   /* The parser will print an error message for us, so we silently return.  */
427   if (sim_parse_args (sd, argv) != SIM_RC_OK)
428     {
429       /* Uninstall the modules to avoid memory leaks,
430          file descriptor leaks, etc.  */
431       free_state (sd);
432       return 0;
433     }
434
435   /* Check for/establish the a reference program image.  */
436   if (sim_analyze_program (sd,
437                            (STATE_PROG_ARGV (sd) != NULL
438                             ? *STATE_PROG_ARGV (sd)
439                             : NULL), abfd) != SIM_RC_OK)
440     {
441       free_state (sd);
442       return 0;
443     }
444
445   /* Establish any remaining configuration options.  */
446   if (sim_config (sd) != SIM_RC_OK)
447     {
448       free_state (sd);
449       return 0;
450     }
451
452   if (sim_post_argv_init (sd) != SIM_RC_OK)
453     {
454       /* Uninstall the modules to avoid memory leaks,
455          file descriptor leaks, etc.  */
456       free_state (sd);
457       return 0;
458     }
459   if (sim_prepare_for_program (sd, abfd) != SIM_RC_OK)
460     {
461       free_state (sd);
462       return 0;
463     }      
464
465   /* CPU specific initialization.  */
466   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
467     {
468       SIM_CPU *cpu = STATE_CPU (sd, i);
469
470       CPU_REG_FETCH (cpu) = m68hc11_reg_fetch;
471       CPU_REG_STORE (cpu) = m68hc11_reg_store;
472       CPU_PC_FETCH (cpu) = m68hc11_pc_get;
473       CPU_PC_STORE (cpu) = m68hc11_pc_set;
474     }
475
476   return sd;
477 }
478
479 /* Generic implementation of sim_engine_run that works within the
480    sim_engine setjmp/longjmp framework. */
481
482 void
483 sim_engine_run (SIM_DESC sd,
484                 int next_cpu_nr,        /* ignore */
485                 int nr_cpus,    /* ignore */
486                 int siggnal)    /* ignore */
487 {
488   sim_cpu *cpu;
489
490   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
491   cpu = STATE_CPU (sd, 0);
492   while (1)
493     {
494       cpu_single_step (cpu);
495
496       /* process any events */
497       if (sim_events_tickn (sd, cpu->cpu_current_cycle))
498         {
499           sim_events_process (sd);
500         }
501     }
502 }
503
504 void
505 sim_info (SIM_DESC sd, int verbose)
506 {
507   const char *cpu_type;
508   const struct bfd_arch_info *arch;
509
510   /* Nothing to do if there is no verbose flag set.  */
511   if (verbose == 0 && STATE_VERBOSE_P (sd) == 0)
512     return;
513
514   arch = STATE_ARCHITECTURE (sd);
515   if (arch->arch == bfd_arch_m68hc11)
516     cpu_type = "68HC11";
517   else
518     cpu_type = "68HC12";
519
520   sim_io_eprintf (sd, "Simulator info:\n");
521   sim_io_eprintf (sd, "  CPU Motorola %s\n", cpu_type);
522   sim_get_info (sd, 0);
523   sim_module_info (sd, verbose || STATE_VERBOSE_P (sd));
524 }
525
526 SIM_RC
527 sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
528                      char * const *argv, char * const *env)
529 {
530   return sim_prepare_for_program (sd, abfd);
531 }
532
533 static int
534 m68hc11_reg_fetch (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
535 {
536   uint16 val;
537   int size = 2;
538
539   switch (rn)
540     {
541     case A_REGNUM:
542       val = cpu_get_a (cpu);
543       size = 1;
544       break;
545
546     case B_REGNUM:
547       val = cpu_get_b (cpu);
548       size = 1;
549       break;
550
551     case D_REGNUM:
552       val = cpu_get_d (cpu);
553       break;
554
555     case X_REGNUM:
556       val = cpu_get_x (cpu);
557       break;
558
559     case Y_REGNUM:
560       val = cpu_get_y (cpu);
561       break;
562
563     case SP_REGNUM:
564       val = cpu_get_sp (cpu);
565       break;
566
567     case PC_REGNUM:
568       val = cpu_get_pc (cpu);
569       break;
570
571     case PSW_REGNUM:
572       val = cpu_get_ccr (cpu);
573       size = 1;
574       break;
575
576     case PAGE_REGNUM:
577       val = cpu_get_page (cpu);
578       size = 1;
579       break;
580
581     default:
582       val = 0;
583       break;
584     }
585   if (size == 1)
586     {
587       memory[0] = val;
588     }
589   else
590     {
591       memory[0] = val >> 8;
592       memory[1] = val & 0x0FF;
593     }
594   return size;
595 }
596
597 static int
598 m68hc11_reg_store (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
599 {
600   uint16 val;
601
602   val = *memory++;
603   if (length == 2)
604     val = (val << 8) | *memory;
605
606   switch (rn)
607     {
608     case D_REGNUM:
609       cpu_set_d (cpu, val);
610       break;
611
612     case A_REGNUM:
613       cpu_set_a (cpu, val);
614       return 1;
615
616     case B_REGNUM:
617       cpu_set_b (cpu, val);
618       return 1;
619
620     case X_REGNUM:
621       cpu_set_x (cpu, val);
622       break;
623
624     case Y_REGNUM:
625       cpu_set_y (cpu, val);
626       break;
627
628     case SP_REGNUM:
629       cpu_set_sp (cpu, val);
630       break;
631
632     case PC_REGNUM:
633       cpu_set_pc (cpu, val);
634       break;
635
636     case PSW_REGNUM:
637       cpu_set_ccr (cpu, val);
638       return 1;
639
640     case PAGE_REGNUM:
641       cpu_set_page (cpu, val);
642       return 1;
643
644     default:
645       break;
646     }
647
648   return 2;
649 }
This page took 0.061166 seconds and 4 git commands to generate.