xref: /netbsd-src/external/gpl3/gdb/dist/sim/m32r/m32rx.c (revision 05fa08567a80471fd0eb3843a238392874f2577c)
14e98e3e1Schristos /* m32rx simulator support code
2*05fa0856Schristos    Copyright (C) 1997-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 
234e98e3e1Schristos #define WANT_CPU m32rxf
244e98e3e1Schristos #define WANT_CPU_M32RXF
254e98e3e1Schristos 
264e98e3e1Schristos #include "sim-main.h"
274e98e3e1Schristos #include "cgen-mem.h"
284e98e3e1Schristos #include "cgen-ops.h"
294e98e3e1Schristos 
30*05fa0856Schristos #include "m32r-sim.h"
31*05fa0856Schristos 
324e98e3e1Schristos /* The contents of BUF are in target byte order.  */
334e98e3e1Schristos 
344e98e3e1Schristos int
354b169a6bSchristos m32rxf_fetch_register (SIM_CPU *current_cpu, int rn, void *buf, int len)
364e98e3e1Schristos {
374e98e3e1Schristos   return m32rbf_fetch_register (current_cpu, rn, buf, len);
384e98e3e1Schristos }
394e98e3e1Schristos 
404e98e3e1Schristos /* The contents of BUF are in target byte order.  */
414e98e3e1Schristos 
424e98e3e1Schristos int
434b169a6bSchristos m32rxf_store_register (SIM_CPU *current_cpu, int rn, const void *buf, int len)
444e98e3e1Schristos {
454e98e3e1Schristos   return m32rbf_store_register (current_cpu, rn, buf, len);
464e98e3e1Schristos }
474e98e3e1Schristos 
484e98e3e1Schristos /* Cover fns to get/set the control registers.
494e98e3e1Schristos    FIXME: Duplicated from m32r.c.  The issue is structure offsets.  */
504e98e3e1Schristos 
514e98e3e1Schristos USI
524e98e3e1Schristos m32rxf_h_cr_get_handler (SIM_CPU *current_cpu, UINT cr)
534e98e3e1Schristos {
544e98e3e1Schristos   switch (cr)
554e98e3e1Schristos     {
564e98e3e1Schristos     case H_CR_PSW : /* psw */
574e98e3e1Schristos       return (((CPU (h_bpsw) & 0xc1) << 8)
584e98e3e1Schristos 	      | ((CPU (h_psw) & 0xc0) << 0)
594e98e3e1Schristos 	      | GET_H_COND ());
604e98e3e1Schristos     case H_CR_BBPSW : /* backup backup psw */
614e98e3e1Schristos       return CPU (h_bbpsw) & 0xc1;
624e98e3e1Schristos     case H_CR_CBR : /* condition bit */
634e98e3e1Schristos       return GET_H_COND ();
644e98e3e1Schristos     case H_CR_SPI : /* interrupt stack pointer */
654e98e3e1Schristos       if (! GET_H_SM ())
664e98e3e1Schristos 	return CPU (h_gr[H_GR_SP]);
674e98e3e1Schristos       else
684e98e3e1Schristos 	return CPU (h_cr[H_CR_SPI]);
694e98e3e1Schristos     case H_CR_SPU : /* user stack pointer */
704e98e3e1Schristos       if (GET_H_SM ())
714e98e3e1Schristos 	return CPU (h_gr[H_GR_SP]);
724e98e3e1Schristos       else
734e98e3e1Schristos 	return CPU (h_cr[H_CR_SPU]);
744e98e3e1Schristos     case H_CR_BPC : /* backup pc */
754e98e3e1Schristos       return CPU (h_cr[H_CR_BPC]) & 0xfffffffe;
764e98e3e1Schristos     case H_CR_BBPC : /* backup backup pc */
774e98e3e1Schristos       return CPU (h_cr[H_CR_BBPC]) & 0xfffffffe;
784e98e3e1Schristos     case 4 : /* ??? unspecified, but apparently available */
794e98e3e1Schristos     case 5 : /* ??? unspecified, but apparently available */
804e98e3e1Schristos       return CPU (h_cr[cr]);
814e98e3e1Schristos     default :
824e98e3e1Schristos       return 0;
834e98e3e1Schristos     }
844e98e3e1Schristos }
854e98e3e1Schristos 
864e98e3e1Schristos void
874e98e3e1Schristos m32rxf_h_cr_set_handler (SIM_CPU *current_cpu, UINT cr, USI newval)
884e98e3e1Schristos {
894e98e3e1Schristos   switch (cr)
904e98e3e1Schristos     {
914e98e3e1Schristos     case H_CR_PSW : /* psw */
924e98e3e1Schristos       {
934e98e3e1Schristos 	int old_sm = (CPU (h_psw) & 0x80) != 0;
944e98e3e1Schristos 	int new_sm = (newval & 0x80) != 0;
954e98e3e1Schristos 	CPU (h_bpsw) = (newval >> 8) & 0xff;
964e98e3e1Schristos 	CPU (h_psw) = newval & 0xff;
974e98e3e1Schristos 	SET_H_COND (newval & 1);
984e98e3e1Schristos 	/* When switching stack modes, update the registers.  */
994e98e3e1Schristos 	if (old_sm != new_sm)
1004e98e3e1Schristos 	  {
1014e98e3e1Schristos 	    if (old_sm)
1024e98e3e1Schristos 	      {
1034e98e3e1Schristos 		/* Switching user -> system.  */
1044e98e3e1Schristos 		CPU (h_cr[H_CR_SPU]) = CPU (h_gr[H_GR_SP]);
1054e98e3e1Schristos 		CPU (h_gr[H_GR_SP]) = CPU (h_cr[H_CR_SPI]);
1064e98e3e1Schristos 	      }
1074e98e3e1Schristos 	    else
1084e98e3e1Schristos 	      {
1094e98e3e1Schristos 		/* Switching system -> user.  */
1104e98e3e1Schristos 		CPU (h_cr[H_CR_SPI]) = CPU (h_gr[H_GR_SP]);
1114e98e3e1Schristos 		CPU (h_gr[H_GR_SP]) = CPU (h_cr[H_CR_SPU]);
1124e98e3e1Schristos 	      }
1134e98e3e1Schristos 	  }
1144e98e3e1Schristos 	break;
1154e98e3e1Schristos       }
1164e98e3e1Schristos     case H_CR_BBPSW : /* backup backup psw */
1174e98e3e1Schristos       CPU (h_bbpsw) = newval & 0xff;
1184e98e3e1Schristos       break;
1194e98e3e1Schristos     case H_CR_CBR : /* condition bit */
1204e98e3e1Schristos       SET_H_COND (newval & 1);
1214e98e3e1Schristos       break;
1224e98e3e1Schristos     case H_CR_SPI : /* interrupt stack pointer */
1234e98e3e1Schristos       if (! GET_H_SM ())
1244e98e3e1Schristos 	CPU (h_gr[H_GR_SP]) = newval;
1254e98e3e1Schristos       else
1264e98e3e1Schristos 	CPU (h_cr[H_CR_SPI]) = newval;
1274e98e3e1Schristos       break;
1284e98e3e1Schristos     case H_CR_SPU : /* user stack pointer */
1294e98e3e1Schristos       if (GET_H_SM ())
1304e98e3e1Schristos 	CPU (h_gr[H_GR_SP]) = newval;
1314e98e3e1Schristos       else
1324e98e3e1Schristos 	CPU (h_cr[H_CR_SPU]) = newval;
1334e98e3e1Schristos       break;
1344e98e3e1Schristos     case H_CR_BPC : /* backup pc */
1354e98e3e1Schristos       CPU (h_cr[H_CR_BPC]) = newval;
1364e98e3e1Schristos       break;
1374e98e3e1Schristos     case H_CR_BBPC : /* backup backup pc */
1384e98e3e1Schristos       CPU (h_cr[H_CR_BBPC]) = newval;
1394e98e3e1Schristos       break;
1404e98e3e1Schristos     case 4 : /* ??? unspecified, but apparently available */
1414e98e3e1Schristos     case 5 : /* ??? unspecified, but apparently available */
1424e98e3e1Schristos       CPU (h_cr[cr]) = newval;
1434e98e3e1Schristos       break;
1444e98e3e1Schristos     default :
1454e98e3e1Schristos       /* ignore */
1464e98e3e1Schristos       break;
1474e98e3e1Schristos     }
1484e98e3e1Schristos }
1494e98e3e1Schristos 
1504e98e3e1Schristos /* Cover fns to access h-psw.  */
1514e98e3e1Schristos 
1524e98e3e1Schristos UQI
1534e98e3e1Schristos m32rxf_h_psw_get_handler (SIM_CPU *current_cpu)
1544e98e3e1Schristos {
1554e98e3e1Schristos   return (CPU (h_psw) & 0xfe) | (CPU (h_cond) & 1);
1564e98e3e1Schristos }
1574e98e3e1Schristos 
1584e98e3e1Schristos void
1594e98e3e1Schristos m32rxf_h_psw_set_handler (SIM_CPU *current_cpu, UQI newval)
1604e98e3e1Schristos {
1614e98e3e1Schristos   CPU (h_psw) = newval;
1624e98e3e1Schristos   CPU (h_cond) = newval & 1;
1634e98e3e1Schristos }
1644e98e3e1Schristos 
1654e98e3e1Schristos /* Cover fns to access h-accum.  */
1664e98e3e1Schristos 
1674e98e3e1Schristos DI
1684e98e3e1Schristos m32rxf_h_accum_get_handler (SIM_CPU *current_cpu)
1694e98e3e1Schristos {
1704e98e3e1Schristos   /* Sign extend the top 8 bits.  */
1714e98e3e1Schristos   DI r;
1724e98e3e1Schristos   r = ANDDI (CPU (h_accum), MAKEDI (0xffffff, 0xffffffff));
1734e98e3e1Schristos   r = XORDI (r, MAKEDI (0x800000, 0));
1744e98e3e1Schristos   r = SUBDI (r, MAKEDI (0x800000, 0));
1754e98e3e1Schristos   return r;
1764e98e3e1Schristos }
1774e98e3e1Schristos 
1784e98e3e1Schristos void
1794e98e3e1Schristos m32rxf_h_accum_set_handler (SIM_CPU *current_cpu, DI newval)
1804e98e3e1Schristos {
1814e98e3e1Schristos   CPU (h_accum) = newval;
1824e98e3e1Schristos }
1834e98e3e1Schristos 
1844e98e3e1Schristos /* Cover fns to access h-accums.  */
1854e98e3e1Schristos 
1864e98e3e1Schristos DI
1874e98e3e1Schristos m32rxf_h_accums_get_handler (SIM_CPU *current_cpu, UINT regno)
1884e98e3e1Schristos {
1894e98e3e1Schristos   /* FIXME: Yes, this is just a quick hack.  */
1904e98e3e1Schristos   DI r;
1914e98e3e1Schristos   if (regno == 0)
1924e98e3e1Schristos     r = CPU (h_accum);
1934e98e3e1Schristos   else
1944e98e3e1Schristos     r = CPU (h_accums[1]);
1954e98e3e1Schristos   /* Sign extend the top 8 bits.  */
1964e98e3e1Schristos   r = ANDDI (r, MAKEDI (0xffffff, 0xffffffff));
1974e98e3e1Schristos   r = XORDI (r, MAKEDI (0x800000, 0));
1984e98e3e1Schristos   r = SUBDI (r, MAKEDI (0x800000, 0));
1994e98e3e1Schristos   return r;
2004e98e3e1Schristos }
2014e98e3e1Schristos 
2024e98e3e1Schristos void
2034e98e3e1Schristos m32rxf_h_accums_set_handler (SIM_CPU *current_cpu, UINT regno, DI newval)
2044e98e3e1Schristos {
2054e98e3e1Schristos   /* FIXME: Yes, this is just a quick hack.  */
2064e98e3e1Schristos   if (regno == 0)
2074e98e3e1Schristos     CPU (h_accum) = newval;
2084e98e3e1Schristos   else
2094e98e3e1Schristos     CPU (h_accums[1]) = newval;
2104e98e3e1Schristos }
2114e98e3e1Schristos 
2124e98e3e1Schristos #if WITH_PROFILE_MODEL_P
2134e98e3e1Schristos 
2144e98e3e1Schristos /* Initialize cycle counting for an insn.
2154e98e3e1Schristos    FIRST_P is non-zero if this is the first insn in a set of parallel
2164e98e3e1Schristos    insns.  */
2174e98e3e1Schristos 
2184e98e3e1Schristos void
2194e98e3e1Schristos m32rxf_model_insn_before (SIM_CPU *cpu, int first_p)
2204e98e3e1Schristos {
2214e98e3e1Schristos   m32rbf_model_insn_before (cpu, first_p);
2224e98e3e1Schristos }
2234e98e3e1Schristos 
2244e98e3e1Schristos /* Record the cycles computed for an insn.
2254e98e3e1Schristos    LAST_P is non-zero if this is the last insn in a set of parallel insns,
2264e98e3e1Schristos    and we update the total cycle count.
2274e98e3e1Schristos    CYCLES is the cycle count of the insn.  */
2284e98e3e1Schristos 
2294e98e3e1Schristos void
2304e98e3e1Schristos m32rxf_model_insn_after (SIM_CPU *cpu, int last_p, int cycles)
2314e98e3e1Schristos {
2324e98e3e1Schristos   m32rbf_model_insn_after (cpu, last_p, cycles);
2334e98e3e1Schristos }
2344e98e3e1Schristos 
2354e98e3e1Schristos static INLINE void
2364e98e3e1Schristos check_load_stall (SIM_CPU *cpu, int regno)
2374e98e3e1Schristos {
2384e98e3e1Schristos   UINT h_gr = CPU_M32R_MISC_PROFILE (cpu)->load_regs;
2394e98e3e1Schristos 
2404e98e3e1Schristos   if (regno != -1
2414e98e3e1Schristos       && (h_gr & (1 << regno)) != 0)
2424e98e3e1Schristos     {
2434e98e3e1Schristos       CPU_M32R_MISC_PROFILE (cpu)->load_stall += 2;
2444e98e3e1Schristos       if (TRACE_INSN_P (cpu))
2454e98e3e1Schristos 	cgen_trace_printf (cpu, " ; Load stall of 2 cycles.");
2464e98e3e1Schristos     }
2474e98e3e1Schristos }
2484e98e3e1Schristos 
2494e98e3e1Schristos int
2504e98e3e1Schristos m32rxf_model_m32rx_u_exec (SIM_CPU *cpu, const IDESC *idesc,
2514e98e3e1Schristos 			   int unit_num, int referenced,
2524e98e3e1Schristos 			   INT sr, INT sr2, INT dr)
2534e98e3e1Schristos {
2544e98e3e1Schristos   check_load_stall (cpu, sr);
2554e98e3e1Schristos   check_load_stall (cpu, sr2);
2564e98e3e1Schristos   return idesc->timing->units[unit_num].done;
2574e98e3e1Schristos }
2584e98e3e1Schristos 
2594e98e3e1Schristos int
2604e98e3e1Schristos m32rxf_model_m32rx_u_cmp (SIM_CPU *cpu, const IDESC *idesc,
2614e98e3e1Schristos 			   int unit_num, int referenced,
2624e98e3e1Schristos 			   INT src1, INT src2)
2634e98e3e1Schristos {
2644e98e3e1Schristos   check_load_stall (cpu, src1);
2654e98e3e1Schristos   check_load_stall (cpu, src2);
2664e98e3e1Schristos   return idesc->timing->units[unit_num].done;
2674e98e3e1Schristos }
2684e98e3e1Schristos 
2694e98e3e1Schristos int
2704e98e3e1Schristos m32rxf_model_m32rx_u_mac (SIM_CPU *cpu, const IDESC *idesc,
2714e98e3e1Schristos 			   int unit_num, int referenced,
2724e98e3e1Schristos 			   INT src1, INT src2)
2734e98e3e1Schristos {
2744e98e3e1Schristos   check_load_stall (cpu, src1);
2754e98e3e1Schristos   check_load_stall (cpu, src2);
2764e98e3e1Schristos   return idesc->timing->units[unit_num].done;
2774e98e3e1Schristos }
2784e98e3e1Schristos 
2794e98e3e1Schristos int
2804e98e3e1Schristos m32rxf_model_m32rx_u_cti (SIM_CPU *cpu, const IDESC *idesc,
2814e98e3e1Schristos 			  int unit_num, int referenced,
2824e98e3e1Schristos 			  INT sr)
2834e98e3e1Schristos {
2844e98e3e1Schristos   PROFILE_DATA *profile = CPU_PROFILE_DATA (cpu);
2854e98e3e1Schristos   int taken_p = (referenced & (1 << 1)) != 0;
2864e98e3e1Schristos 
2874e98e3e1Schristos   check_load_stall (cpu, sr);
2884e98e3e1Schristos   if (taken_p)
2894e98e3e1Schristos     {
2904e98e3e1Schristos       CPU_M32R_MISC_PROFILE (cpu)->cti_stall += 2;
2914e98e3e1Schristos       PROFILE_MODEL_TAKEN_COUNT (profile) += 1;
2924e98e3e1Schristos     }
2934e98e3e1Schristos   else
2944e98e3e1Schristos     PROFILE_MODEL_UNTAKEN_COUNT (profile) += 1;
2954e98e3e1Schristos   return idesc->timing->units[unit_num].done;
2964e98e3e1Schristos }
2974e98e3e1Schristos 
2984e98e3e1Schristos int
2994e98e3e1Schristos m32rxf_model_m32rx_u_load (SIM_CPU *cpu, const IDESC *idesc,
3004e98e3e1Schristos 			   int unit_num, int referenced,
3014e98e3e1Schristos 			   INT sr, INT dr)
3024e98e3e1Schristos {
3034e98e3e1Schristos   CPU_M32R_MISC_PROFILE (cpu)->load_regs_pending |= (1 << dr);
3044e98e3e1Schristos   return idesc->timing->units[unit_num].done;
3054e98e3e1Schristos }
3064e98e3e1Schristos 
3074e98e3e1Schristos int
3084e98e3e1Schristos m32rxf_model_m32rx_u_store (SIM_CPU *cpu, const IDESC *idesc,
3094e98e3e1Schristos 			    int unit_num, int referenced,
3104e98e3e1Schristos 			    INT src1, INT src2)
3114e98e3e1Schristos {
3124e98e3e1Schristos   return idesc->timing->units[unit_num].done;
3134e98e3e1Schristos }
3144e98e3e1Schristos 
3154e98e3e1Schristos #endif /* WITH_PROFILE_MODEL_P */
316