xref: /netbsd-src/external/gpl3/gdb/dist/sim/m32r/sim-if.c (revision 05fa08567a80471fd0eb3843a238392874f2577c)
1 /* Main simulator entry points specific to the M32R.
2    Copyright (C) 1996-2024 Free Software Foundation, Inc.
3    Contributed by Cygnus Support.
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 <string.h>
24 #include <stdlib.h>
25 
26 #include "sim/callback.h"
27 #include "sim-main.h"
28 #include "sim-hw.h"
29 #include "sim-options.h"
30 #include "libiberty.h"
31 #include "bfd.h"
32 
33 #include "m32r-sim.h"
34 #include "dv-m32r_uart.h"
35 
36 #define M32R_DEFAULT_MEM_SIZE 0x2000000 /* 32M */
37 
38 static void free_state (SIM_DESC);
39 static void print_m32r_misc_cpu (SIM_CPU *cpu, bool verbose);
40 
41 /* Cover function of sim_state_free to free the cpu buffers as well.  */
42 
43 static void
44 free_state (SIM_DESC sd)
45 {
46   if (STATE_MODULES (sd) != NULL)
47     sim_module_uninstall (sd);
48   sim_cpu_free_all (sd);
49   sim_state_free (sd);
50 }
51 
52 extern const SIM_MACH * const m32r_sim_machs[];
53 
54 /* Create an instance of the simulator.  */
55 
56 SIM_DESC
57 sim_open (SIM_OPEN_KIND kind, host_callback *callback, struct bfd *abfd,
58 	  char * const *argv)
59 {
60   SIM_DESC sd = sim_state_alloc (kind, callback);
61   char c;
62   int i;
63 
64   /* Set default options before parsing user options.  */
65   STATE_MACHS (sd) = m32r_sim_machs;
66   STATE_MODEL_NAME (sd) = "m32r/d";
67   current_alignment = STRICT_ALIGNMENT;
68   current_target_byte_order = BFD_ENDIAN_BIG;
69 
70   /* The cpu data is kept in a separately allocated chunk of memory.  */
71   if (sim_cpu_alloc_all_extra (sd, 0, sizeof (struct m32r_sim_cpu))
72       != SIM_RC_OK)
73     {
74       free_state (sd);
75       return 0;
76     }
77 
78   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
79     {
80       free_state (sd);
81       return 0;
82     }
83 
84   /* The parser will print an error message for us, so we silently return.  */
85   if (sim_parse_args (sd, argv) != SIM_RC_OK)
86     {
87       free_state (sd);
88       return 0;
89     }
90 
91   /* Allocate a handler for the control registers and other devices
92      if no memory for that range has been allocated by the user.
93      All are allocated in one chunk to keep things from being
94      unnecessarily complicated.
95      TODO: Move these to the sim-model framework.  */
96   sim_hw_parse (sd, "/core/%s/reg %#x %i", "m32r_uart", UART_BASE_ADDR, 0x100);
97   sim_hw_parse (sd, "/core/%s/reg %#x %i", "m32r_cache", 0xfffffff0, 0x10);
98 
99   /* Allocate core managed memory if none specified by user.
100      Use address 4 here in case the user wanted address 0 unmapped.  */
101   if (sim_core_read_buffer (sd, NULL, read_map, &c, 4, 1) == 0)
102     sim_do_commandf (sd, "memory region 0,0x%x", M32R_DEFAULT_MEM_SIZE);
103 
104   /* check for/establish the reference program image */
105   if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
106     {
107       free_state (sd);
108       return 0;
109     }
110 
111   /* Establish any remaining configuration options.  */
112   if (sim_config (sd) != SIM_RC_OK)
113     {
114       free_state (sd);
115       return 0;
116     }
117 
118   if (sim_post_argv_init (sd) != SIM_RC_OK)
119     {
120       free_state (sd);
121       return 0;
122     }
123 
124   /* Open a copy of the cpu descriptor table.  */
125   {
126     CGEN_CPU_DESC cd = m32r_cgen_cpu_open_1 (STATE_ARCHITECTURE (sd)->printable_name,
127 					     CGEN_ENDIAN_BIG);
128     for (i = 0; i < MAX_NR_PROCESSORS; ++i)
129       {
130 	SIM_CPU *cpu = STATE_CPU (sd, i);
131 	CPU_CPU_DESC (cpu) = cd;
132 	CPU_DISASSEMBLER (cpu) = sim_cgen_disassemble_insn;
133       }
134     m32r_cgen_init_dis (cd);
135   }
136 
137   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
138     {
139       /* Only needed for profiling, but the structure member is small.  */
140       memset (CPU_M32R_MISC_PROFILE (STATE_CPU (sd, i)), 0,
141 	      sizeof (* CPU_M32R_MISC_PROFILE (STATE_CPU (sd, i))));
142       /* Hook in callback for reporting these stats */
143       PROFILE_INFO_CPU_CALLBACK (CPU_PROFILE_DATA (STATE_CPU (sd, i)))
144 	= print_m32r_misc_cpu;
145     }
146 
147   return sd;
148 }
149 
150 SIM_RC
151 sim_create_inferior (SIM_DESC sd, struct bfd *abfd, char * const *argv,
152 		     char * const *env)
153 {
154   SIM_CPU *current_cpu = STATE_CPU (sd, 0);
155   host_callback *cb = STATE_CALLBACK (sd);
156   bfd_vma addr;
157 
158   if (abfd != NULL)
159     addr = bfd_get_start_address (abfd);
160   else
161     addr = 0;
162   sim_pc_set (current_cpu, addr);
163 
164   if (STATE_ENVIRONMENT (sd) == USER_ENVIRONMENT)
165     {
166       m32rbf_h_cr_set (current_cpu,
167 		       m32r_decode_gdb_ctrl_regnum(SPI_REGNUM), 0x1f00000);
168       m32rbf_h_cr_set (current_cpu,
169 		       m32r_decode_gdb_ctrl_regnum(SPU_REGNUM), 0x1f00000);
170     }
171 
172   /* Standalone mode (i.e. `run`) will take care of the argv for us in
173      sim_open() -> sim_parse_args().  But in debug mode (i.e. 'target sim'
174      with `gdb`), we need to handle it because the user can change the
175      argv on the fly via gdb's 'run'.  */
176   if (STATE_PROG_ARGV (sd) != argv)
177     {
178       freeargv (STATE_PROG_ARGV (sd));
179       STATE_PROG_ARGV (sd) = dupargv (argv);
180     }
181 
182   if (STATE_PROG_ENVP (sd) != env)
183     {
184       freeargv (STATE_PROG_ENVP (sd));
185       STATE_PROG_ENVP (sd) = dupargv (env);
186     }
187 
188   cb->argv = STATE_PROG_ARGV (sd);
189   cb->envp = STATE_PROG_ENVP (sd);
190 
191   return SIM_RC_OK;
192 }
193 
194 /* PROFILE_CPU_CALLBACK */
195 
196 static void
197 print_m32r_misc_cpu (SIM_CPU *cpu, bool verbose)
198 {
199   SIM_DESC sd = CPU_STATE (cpu);
200   char buf[20];
201 
202   if (CPU_PROFILE_FLAGS (cpu) [PROFILE_INSN_IDX])
203     {
204       sim_io_printf (sd, "Miscellaneous Statistics\n\n");
205       sim_io_printf (sd, "  %-*s %s\n\n",
206 		     PROFILE_LABEL_WIDTH, "Fill nops:",
207 		     sim_add_commas (buf, sizeof (buf),
208 				     CPU_M32R_MISC_PROFILE (cpu)->fillnop_count));
209       if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_m32rx)
210 	sim_io_printf (sd, "  %-*s %s\n\n",
211 		       PROFILE_LABEL_WIDTH, "Parallel insns:",
212 		       sim_add_commas (buf, sizeof (buf),
213 				       CPU_M32R_MISC_PROFILE (cpu)->parallel_count));
214       if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_m32r2)
215 	sim_io_printf (sd, "  %-*s %s\n\n",
216 		       PROFILE_LABEL_WIDTH, "Parallel insns:",
217 		       sim_add_commas (buf, sizeof (buf),
218 				       CPU_M32R_MISC_PROFILE (cpu)->parallel_count));
219     }
220 }
221