xref: /netbsd-src/external/gpl3/gdb/dist/sim/m32r/sim-if.c (revision 05fa08567a80471fd0eb3843a238392874f2577c)
14e98e3e1Schristos /* Main simulator entry points specific to the M32R.
2*05fa0856Schristos    Copyright (C) 1996-2024 Free Software Foundation, Inc.
34e98e3e1Schristos    Contributed by Cygnus Support.
44e98e3e1Schristos 
54e98e3e1Schristos    This file is part of GDB, the GNU debugger.
64e98e3e1Schristos 
74e98e3e1Schristos    This program is free software; you can redistribute it and/or modify
84e98e3e1Schristos    it under the terms of the GNU General Public License as published by
94e98e3e1Schristos    the Free Software Foundation; either version 3 of the License, or
104e98e3e1Schristos    (at your option) any later version.
114e98e3e1Schristos 
124e98e3e1Schristos    This program is distributed in the hope that it will be useful,
134e98e3e1Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
144e98e3e1Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
154e98e3e1Schristos    GNU General Public License for more details.
164e98e3e1Schristos 
174e98e3e1Schristos    You should have received a copy of the GNU General Public License
184e98e3e1Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
194e98e3e1Schristos 
204b169a6bSchristos /* This must come before any other includes.  */
214b169a6bSchristos #include "defs.h"
224b169a6bSchristos 
234b169a6bSchristos #include <string.h>
244b169a6bSchristos #include <stdlib.h>
254b169a6bSchristos 
264b169a6bSchristos #include "sim/callback.h"
274e98e3e1Schristos #include "sim-main.h"
28*05fa0856Schristos #include "sim-hw.h"
294e98e3e1Schristos #include "sim-options.h"
304e98e3e1Schristos #include "libiberty.h"
314e98e3e1Schristos #include "bfd.h"
324e98e3e1Schristos 
33*05fa0856Schristos #include "m32r-sim.h"
34ba340e45Schristos #include "dv-m32r_uart.h"
35ba340e45Schristos 
364b169a6bSchristos #define M32R_DEFAULT_MEM_SIZE 0x2000000 /* 32M */
374b169a6bSchristos 
384e98e3e1Schristos static void free_state (SIM_DESC);
39*05fa0856Schristos static void print_m32r_misc_cpu (SIM_CPU *cpu, bool verbose);
404e98e3e1Schristos 
414e98e3e1Schristos /* Cover function of sim_state_free to free the cpu buffers as well.  */
424e98e3e1Schristos 
434e98e3e1Schristos static void
444e98e3e1Schristos free_state (SIM_DESC sd)
454e98e3e1Schristos {
464e98e3e1Schristos   if (STATE_MODULES (sd) != NULL)
474e98e3e1Schristos     sim_module_uninstall (sd);
484e98e3e1Schristos   sim_cpu_free_all (sd);
494e98e3e1Schristos   sim_state_free (sd);
504e98e3e1Schristos }
514e98e3e1Schristos 
524b169a6bSchristos extern const SIM_MACH * const m32r_sim_machs[];
534b169a6bSchristos 
544e98e3e1Schristos /* Create an instance of the simulator.  */
554e98e3e1Schristos 
564e98e3e1Schristos SIM_DESC
574b169a6bSchristos sim_open (SIM_OPEN_KIND kind, host_callback *callback, struct bfd *abfd,
584b169a6bSchristos 	  char * const *argv)
594e98e3e1Schristos {
604e98e3e1Schristos   SIM_DESC sd = sim_state_alloc (kind, callback);
614e98e3e1Schristos   char c;
624e98e3e1Schristos   int i;
634e98e3e1Schristos 
644b169a6bSchristos   /* Set default options before parsing user options.  */
654b169a6bSchristos   STATE_MACHS (sd) = m32r_sim_machs;
664b169a6bSchristos   STATE_MODEL_NAME (sd) = "m32r/d";
674b169a6bSchristos   current_alignment = STRICT_ALIGNMENT;
684b169a6bSchristos   current_target_byte_order = BFD_ENDIAN_BIG;
694b169a6bSchristos 
704e98e3e1Schristos   /* The cpu data is kept in a separately allocated chunk of memory.  */
71*05fa0856Schristos   if (sim_cpu_alloc_all_extra (sd, 0, sizeof (struct m32r_sim_cpu))
72*05fa0856Schristos       != SIM_RC_OK)
734e98e3e1Schristos     {
744e98e3e1Schristos       free_state (sd);
754e98e3e1Schristos       return 0;
764e98e3e1Schristos     }
774e98e3e1Schristos 
784e98e3e1Schristos   if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
794e98e3e1Schristos     {
804e98e3e1Schristos       free_state (sd);
814e98e3e1Schristos       return 0;
824e98e3e1Schristos     }
834e98e3e1Schristos 
84ba340e45Schristos   /* The parser will print an error message for us, so we silently return.  */
854e98e3e1Schristos   if (sim_parse_args (sd, argv) != SIM_RC_OK)
864e98e3e1Schristos     {
874e98e3e1Schristos       free_state (sd);
884e98e3e1Schristos       return 0;
894e98e3e1Schristos     }
904e98e3e1Schristos 
914e98e3e1Schristos   /* Allocate a handler for the control registers and other devices
924e98e3e1Schristos      if no memory for that range has been allocated by the user.
934e98e3e1Schristos      All are allocated in one chunk to keep things from being
94ba340e45Schristos      unnecessarily complicated.
95ba340e45Schristos      TODO: Move these to the sim-model framework.  */
96ba340e45Schristos   sim_hw_parse (sd, "/core/%s/reg %#x %i", "m32r_uart", UART_BASE_ADDR, 0x100);
97ba340e45Schristos   sim_hw_parse (sd, "/core/%s/reg %#x %i", "m32r_cache", 0xfffffff0, 0x10);
984e98e3e1Schristos 
994e98e3e1Schristos   /* Allocate core managed memory if none specified by user.
1004e98e3e1Schristos      Use address 4 here in case the user wanted address 0 unmapped.  */
1014e98e3e1Schristos   if (sim_core_read_buffer (sd, NULL, read_map, &c, 4, 1) == 0)
1024e98e3e1Schristos     sim_do_commandf (sd, "memory region 0,0x%x", M32R_DEFAULT_MEM_SIZE);
1034e98e3e1Schristos 
1044e98e3e1Schristos   /* check for/establish the reference program image */
1054b169a6bSchristos   if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
1064e98e3e1Schristos     {
1074e98e3e1Schristos       free_state (sd);
1084e98e3e1Schristos       return 0;
1094e98e3e1Schristos     }
1104e98e3e1Schristos 
1114e98e3e1Schristos   /* Establish any remaining configuration options.  */
1124e98e3e1Schristos   if (sim_config (sd) != SIM_RC_OK)
1134e98e3e1Schristos     {
1144e98e3e1Schristos       free_state (sd);
1154e98e3e1Schristos       return 0;
1164e98e3e1Schristos     }
1174e98e3e1Schristos 
1184e98e3e1Schristos   if (sim_post_argv_init (sd) != SIM_RC_OK)
1194e98e3e1Schristos     {
1204e98e3e1Schristos       free_state (sd);
1214e98e3e1Schristos       return 0;
1224e98e3e1Schristos     }
1234e98e3e1Schristos 
1244e98e3e1Schristos   /* Open a copy of the cpu descriptor table.  */
1254e98e3e1Schristos   {
1264e98e3e1Schristos     CGEN_CPU_DESC cd = m32r_cgen_cpu_open_1 (STATE_ARCHITECTURE (sd)->printable_name,
1274e98e3e1Schristos 					     CGEN_ENDIAN_BIG);
1284e98e3e1Schristos     for (i = 0; i < MAX_NR_PROCESSORS; ++i)
1294e98e3e1Schristos       {
1304e98e3e1Schristos 	SIM_CPU *cpu = STATE_CPU (sd, i);
1314e98e3e1Schristos 	CPU_CPU_DESC (cpu) = cd;
1324e98e3e1Schristos 	CPU_DISASSEMBLER (cpu) = sim_cgen_disassemble_insn;
1334e98e3e1Schristos       }
1344e98e3e1Schristos     m32r_cgen_init_dis (cd);
1354e98e3e1Schristos   }
1364e98e3e1Schristos 
137*05fa0856Schristos   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
1384e98e3e1Schristos     {
1394e98e3e1Schristos       /* Only needed for profiling, but the structure member is small.  */
1404e98e3e1Schristos       memset (CPU_M32R_MISC_PROFILE (STATE_CPU (sd, i)), 0,
1414e98e3e1Schristos 	      sizeof (* CPU_M32R_MISC_PROFILE (STATE_CPU (sd, i))));
1424e98e3e1Schristos       /* Hook in callback for reporting these stats */
1434e98e3e1Schristos       PROFILE_INFO_CPU_CALLBACK (CPU_PROFILE_DATA (STATE_CPU (sd, i)))
1444e98e3e1Schristos 	= print_m32r_misc_cpu;
1454e98e3e1Schristos     }
1464e98e3e1Schristos 
1474e98e3e1Schristos   return sd;
1484e98e3e1Schristos }
1494e98e3e1Schristos 
1504e98e3e1Schristos SIM_RC
1514b169a6bSchristos sim_create_inferior (SIM_DESC sd, struct bfd *abfd, char * const *argv,
1524b169a6bSchristos 		     char * const *env)
1534e98e3e1Schristos {
1544e98e3e1Schristos   SIM_CPU *current_cpu = STATE_CPU (sd, 0);
1554b169a6bSchristos   host_callback *cb = STATE_CALLBACK (sd);
156*05fa0856Schristos   bfd_vma addr;
1574e98e3e1Schristos 
1584e98e3e1Schristos   if (abfd != NULL)
1594e98e3e1Schristos     addr = bfd_get_start_address (abfd);
1604e98e3e1Schristos   else
1614e98e3e1Schristos     addr = 0;
1624e98e3e1Schristos   sim_pc_set (current_cpu, addr);
1634e98e3e1Schristos 
1644b169a6bSchristos   if (STATE_ENVIRONMENT (sd) == USER_ENVIRONMENT)
1654b169a6bSchristos     {
1664e98e3e1Schristos       m32rbf_h_cr_set (current_cpu,
1674e98e3e1Schristos 		       m32r_decode_gdb_ctrl_regnum(SPI_REGNUM), 0x1f00000);
1684e98e3e1Schristos       m32rbf_h_cr_set (current_cpu,
1694e98e3e1Schristos 		       m32r_decode_gdb_ctrl_regnum(SPU_REGNUM), 0x1f00000);
1704b169a6bSchristos     }
1714e98e3e1Schristos 
172ba340e45Schristos   /* Standalone mode (i.e. `run`) will take care of the argv for us in
173ba340e45Schristos      sim_open() -> sim_parse_args().  But in debug mode (i.e. 'target sim'
174ba340e45Schristos      with `gdb`), we need to handle it because the user can change the
175ba340e45Schristos      argv on the fly via gdb's 'run'.  */
176ba340e45Schristos   if (STATE_PROG_ARGV (sd) != argv)
177ba340e45Schristos     {
178ba340e45Schristos       freeargv (STATE_PROG_ARGV (sd));
179ba340e45Schristos       STATE_PROG_ARGV (sd) = dupargv (argv);
180ba340e45Schristos     }
1814e98e3e1Schristos 
1824b169a6bSchristos   if (STATE_PROG_ENVP (sd) != env)
1834b169a6bSchristos     {
1844b169a6bSchristos       freeargv (STATE_PROG_ENVP (sd));
1854b169a6bSchristos       STATE_PROG_ENVP (sd) = dupargv (env);
1864b169a6bSchristos     }
1874b169a6bSchristos 
1884b169a6bSchristos   cb->argv = STATE_PROG_ARGV (sd);
1894b169a6bSchristos   cb->envp = STATE_PROG_ENVP (sd);
1904b169a6bSchristos 
1914e98e3e1Schristos   return SIM_RC_OK;
1924e98e3e1Schristos }
1934e98e3e1Schristos 
1944e98e3e1Schristos /* PROFILE_CPU_CALLBACK */
1954e98e3e1Schristos 
1964e98e3e1Schristos static void
197*05fa0856Schristos print_m32r_misc_cpu (SIM_CPU *cpu, bool verbose)
1984e98e3e1Schristos {
1994e98e3e1Schristos   SIM_DESC sd = CPU_STATE (cpu);
2004e98e3e1Schristos   char buf[20];
2014e98e3e1Schristos 
2024e98e3e1Schristos   if (CPU_PROFILE_FLAGS (cpu) [PROFILE_INSN_IDX])
2034e98e3e1Schristos     {
2044e98e3e1Schristos       sim_io_printf (sd, "Miscellaneous Statistics\n\n");
2054e98e3e1Schristos       sim_io_printf (sd, "  %-*s %s\n\n",
2064e98e3e1Schristos 		     PROFILE_LABEL_WIDTH, "Fill nops:",
2074e98e3e1Schristos 		     sim_add_commas (buf, sizeof (buf),
2084e98e3e1Schristos 				     CPU_M32R_MISC_PROFILE (cpu)->fillnop_count));
2094e98e3e1Schristos       if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_m32rx)
2104e98e3e1Schristos 	sim_io_printf (sd, "  %-*s %s\n\n",
2114e98e3e1Schristos 		       PROFILE_LABEL_WIDTH, "Parallel insns:",
2124e98e3e1Schristos 		       sim_add_commas (buf, sizeof (buf),
2134e98e3e1Schristos 				       CPU_M32R_MISC_PROFILE (cpu)->parallel_count));
2144e98e3e1Schristos       if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_m32r2)
2154e98e3e1Schristos 	sim_io_printf (sd, "  %-*s %s\n\n",
2164e98e3e1Schristos 		       PROFILE_LABEL_WIDTH, "Parallel insns:",
2174e98e3e1Schristos 		       sim_add_commas (buf, sizeof (buf),
2184e98e3e1Schristos 				       CPU_M32R_MISC_PROFILE (cpu)->parallel_count));
2194e98e3e1Schristos     }
2204e98e3e1Schristos }
221