1285612Sdelphij/* m32rx simulator support code
2132451Sroberto   Copyright (C) 1997-2023 Free Software Foundation, Inc.
354359Sroberto   Contributed by Cygnus Support.
4285612Sdelphij
5285612SdelphijThis file is part of GDB, the GNU debugger.
654359Sroberto
754359SrobertoThis program is free software; you can redistribute it and/or modify
854359Srobertoit under the terms of the GNU General Public License as published by
954359Srobertothe Free Software Foundation; either version 3 of the License, or
1054359Sroberto(at your option) any later version.
1154359Sroberto
1254359SrobertoThis program is distributed in the hope that it will be useful,
1354359Srobertobut WITHOUT ANY WARRANTY; without even the implied warranty of
1454359SrobertoMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15106163SrobertoGNU General Public License for more details.
16106163Sroberto
1754359SrobertoYou should have received a copy of the GNU General Public License
18285612Sdelphijalong with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19285612Sdelphij
20285612Sdelphij/* This must come before any other includes.  */
21285612Sdelphij#include "defs.h"
22285612Sdelphij
23285612Sdelphij#define WANT_CPU m32rxf
24285612Sdelphij#define WANT_CPU_M32RXF
25285612Sdelphij
26285612Sdelphij#include "sim-main.h"
27285612Sdelphij#include "cgen-mem.h"
28285612Sdelphij#include "cgen-ops.h"
29285612Sdelphij
30285612Sdelphij/* The contents of BUF are in target byte order.  */
31285612Sdelphij
32285612Sdelphijint
33285612Sdelphijm32rxf_fetch_register (SIM_CPU *current_cpu, int rn, void *buf, int len)
34285612Sdelphij{
35285612Sdelphij  return m32rbf_fetch_register (current_cpu, rn, buf, len);
36285612Sdelphij}
37285612Sdelphij
38285612Sdelphij/* The contents of BUF are in target byte order.  */
39285612Sdelphij
40285612Sdelphijint
41285612Sdelphijm32rxf_store_register (SIM_CPU *current_cpu, int rn, const void *buf, int len)
42285612Sdelphij{
43285612Sdelphij  return m32rbf_store_register (current_cpu, rn, buf, len);
44285612Sdelphij}
45285612Sdelphij
46285612Sdelphij/* Cover fns to get/set the control registers.
47285612Sdelphij   FIXME: Duplicated from m32r.c.  The issue is structure offsets.  */
48285612Sdelphij
49285612SdelphijUSI
50285612Sdelphijm32rxf_h_cr_get_handler (SIM_CPU *current_cpu, UINT cr)
51285612Sdelphij{
52285612Sdelphij  switch (cr)
53285612Sdelphij    {
54285612Sdelphij    case H_CR_PSW : /* psw */
55285612Sdelphij      return (((CPU (h_bpsw) & 0xc1) << 8)
56285612Sdelphij	      | ((CPU (h_psw) & 0xc0) << 0)
57285612Sdelphij	      | GET_H_COND ());
58285612Sdelphij    case H_CR_BBPSW : /* backup backup psw */
59285612Sdelphij      return CPU (h_bbpsw) & 0xc1;
60285612Sdelphij    case H_CR_CBR : /* condition bit */
61285612Sdelphij      return GET_H_COND ();
62285612Sdelphij    case H_CR_SPI : /* interrupt stack pointer */
63285612Sdelphij      if (! GET_H_SM ())
64285612Sdelphij	return CPU (h_gr[H_GR_SP]);
65285612Sdelphij      else
66285612Sdelphij	return CPU (h_cr[H_CR_SPI]);
67285612Sdelphij    case H_CR_SPU : /* user stack pointer */
68285612Sdelphij      if (GET_H_SM ())
69285612Sdelphij	return CPU (h_gr[H_GR_SP]);
70285612Sdelphij      else
71285612Sdelphij	return CPU (h_cr[H_CR_SPU]);
72285612Sdelphij    case H_CR_BPC : /* backup pc */
7354359Sroberto      return CPU (h_cr[H_CR_BPC]) & 0xfffffffe;
74200576Sroberto    case H_CR_BBPC : /* backup backup pc */
7554359Sroberto      return CPU (h_cr[H_CR_BBPC]) & 0xfffffffe;
76200576Sroberto    case 4 : /* ??? unspecified, but apparently available */
77132451Sroberto    case 5 : /* ??? unspecified, but apparently available */
78132451Sroberto      return CPU (h_cr[cr]);
79132451Sroberto    default :
80132451Sroberto      return 0;
8182498Sroberto    }
82132451Sroberto}
8354359Sroberto
8454359Srobertovoid
8554359Srobertom32rxf_h_cr_set_handler (SIM_CPU *current_cpu, UINT cr, USI newval)
8654359Sroberto{
8754359Sroberto  switch (cr)
8854359Sroberto    {
8954359Sroberto    case H_CR_PSW : /* psw */
9054359Sroberto      {
91285612Sdelphij	int old_sm = (CPU (h_psw) & 0x80) != 0;
92182007Sroberto	int new_sm = (newval & 0x80) != 0;
93182007Sroberto	CPU (h_bpsw) = (newval >> 8) & 0xff;
94285612Sdelphij	CPU (h_psw) = newval & 0xff;
95285612Sdelphij	SET_H_COND (newval & 1);
96285612Sdelphij	/* When switching stack modes, update the registers.  */
97285612Sdelphij	if (old_sm != new_sm)
98285612Sdelphij	  {
99285612Sdelphij	    if (old_sm)
100285612Sdelphij	      {
101285612Sdelphij		/* Switching user -> system.  */
102285612Sdelphij		CPU (h_cr[H_CR_SPU]) = CPU (h_gr[H_GR_SP]);
103285612Sdelphij		CPU (h_gr[H_GR_SP]) = CPU (h_cr[H_CR_SPI]);
104285612Sdelphij	      }
105285612Sdelphij	    else
106285612Sdelphij	      {
107285612Sdelphij		/* Switching system -> user.  */
108285612Sdelphij		CPU (h_cr[H_CR_SPI]) = CPU (h_gr[H_GR_SP]);
109285612Sdelphij		CPU (h_gr[H_GR_SP]) = CPU (h_cr[H_CR_SPU]);
110285612Sdelphij	      }
111285612Sdelphij	  }
112285612Sdelphij	break;
113285612Sdelphij      }
114285612Sdelphij    case H_CR_BBPSW : /* backup backup psw */
115285612Sdelphij      CPU (h_bbpsw) = newval & 0xff;
116285612Sdelphij      break;
117285612Sdelphij    case H_CR_CBR : /* condition bit */
118285612Sdelphij      SET_H_COND (newval & 1);
119285612Sdelphij      break;
120289999Sglebius    case H_CR_SPI : /* interrupt stack pointer */
121285612Sdelphij      if (! GET_H_SM ())
122285612Sdelphij	CPU (h_gr[H_GR_SP]) = newval;
123285612Sdelphij      else
124285612Sdelphij	CPU (h_cr[H_CR_SPI]) = newval;
125285612Sdelphij      break;
126285612Sdelphij    case H_CR_SPU : /* user stack pointer */
127285612Sdelphij      if (GET_H_SM ())
128285612Sdelphij	CPU (h_gr[H_GR_SP]) = newval;
129285612Sdelphij      else
130285612Sdelphij	CPU (h_cr[H_CR_SPU]) = newval;
131285612Sdelphij      break;
132182007Sroberto    case H_CR_BPC : /* backup pc */
133182007Sroberto      CPU (h_cr[H_CR_BPC]) = newval;
134285612Sdelphij      break;
135182007Sroberto    case H_CR_BBPC : /* backup backup pc */
136182007Sroberto      CPU (h_cr[H_CR_BBPC]) = newval;
137182007Sroberto      break;
138200576Sroberto    case 4 : /* ??? unspecified, but apparently available */
139182007Sroberto    case 5 : /* ??? unspecified, but apparently available */
140182007Sroberto      CPU (h_cr[cr]) = newval;
141285612Sdelphij      break;
142285612Sdelphij    default :
143285612Sdelphij      /* ignore */
144285612Sdelphij      break;
145285612Sdelphij    }
146285612Sdelphij}
147285612Sdelphij
148285612Sdelphij/* Cover fns to access h-psw.  */
149285612Sdelphij
150182007SrobertoUQI
151285612Sdelphijm32rxf_h_psw_get_handler (SIM_CPU *current_cpu)
152285612Sdelphij{
153285612Sdelphij  return (CPU (h_psw) & 0xfe) | (CPU (h_cond) & 1);
154285612Sdelphij}
155285612Sdelphij
156285612Sdelphijvoid
157285612Sdelphijm32rxf_h_psw_set_handler (SIM_CPU *current_cpu, UQI newval)
158285612Sdelphij{
159285612Sdelphij  CPU (h_psw) = newval;
160285612Sdelphij  CPU (h_cond) = newval & 1;
161285612Sdelphij}
162285612Sdelphij
163285612Sdelphij/* Cover fns to access h-accum.  */
164285612Sdelphij
165285612SdelphijDI
166285612Sdelphijm32rxf_h_accum_get_handler (SIM_CPU *current_cpu)
167200576Sroberto{
168285612Sdelphij  /* Sign extend the top 8 bits.  */
169182007Sroberto  DI r;
170200576Sroberto  r = ANDDI (CPU (h_accum), MAKEDI (0xffffff, 0xffffffff));
171182007Sroberto  r = XORDI (r, MAKEDI (0x800000, 0));
172182007Sroberto  r = SUBDI (r, MAKEDI (0x800000, 0));
173285612Sdelphij  return r;
174285612Sdelphij}
175285612Sdelphij
176285612Sdelphijvoid
177285612Sdelphijm32rxf_h_accum_set_handler (SIM_CPU *current_cpu, DI newval)
178285612Sdelphij{
179285612Sdelphij  CPU (h_accum) = newval;
180285612Sdelphij}
181182007Sroberto
182285612Sdelphij/* Cover fns to access h-accums.  */
183285612Sdelphij
184285612SdelphijDI
185285612Sdelphijm32rxf_h_accums_get_handler (SIM_CPU *current_cpu, UINT regno)
186285612Sdelphij{
187285612Sdelphij  /* FIXME: Yes, this is just a quick hack.  */
188285612Sdelphij  DI r;
189285612Sdelphij  if (regno == 0)
190285612Sdelphij    r = CPU (h_accum);
191285612Sdelphij  else
192285612Sdelphij    r = CPU (h_accums[1]);
193285612Sdelphij  /* Sign extend the top 8 bits.  */
194285612Sdelphij  r = ANDDI (r, MAKEDI (0xffffff, 0xffffffff));
195285612Sdelphij  r = XORDI (r, MAKEDI (0x800000, 0));
196285612Sdelphij  r = SUBDI (r, MAKEDI (0x800000, 0));
197285612Sdelphij  return r;
198285612Sdelphij}
199285612Sdelphij
200285612Sdelphijvoid
201285612Sdelphijm32rxf_h_accums_set_handler (SIM_CPU *current_cpu, UINT regno, DI newval)
202285612Sdelphij{
203285612Sdelphij  /* FIXME: Yes, this is just a quick hack.  */
204285612Sdelphij  if (regno == 0)
205285612Sdelphij    CPU (h_accum) = newval;
206285612Sdelphij  else
207285612Sdelphij    CPU (h_accums[1]) = newval;
208285612Sdelphij}
209285612Sdelphij
210285612Sdelphij#if WITH_PROFILE_MODEL_P
211285612Sdelphij
212285612Sdelphij/* Initialize cycle counting for an insn.
213182007Sroberto   FIRST_P is non-zero if this is the first insn in a set of parallel
214182007Sroberto   insns.  */
215285612Sdelphij
216285612Sdelphijvoid
217285612Sdelphijm32rxf_model_insn_before (SIM_CPU *cpu, int first_p)
218182007Sroberto{
219132451Sroberto  m32rbf_model_insn_before (cpu, first_p);
220285612Sdelphij}
22154359Sroberto
222285612Sdelphij/* Record the cycles computed for an insn.
223182007Sroberto   LAST_P is non-zero if this is the last insn in a set of parallel insns,
224132451Sroberto   and we update the total cycle count.
225132451Sroberto   CYCLES is the cycle count of the insn.  */
226132451Sroberto
22754359Srobertovoid
228289999Sglebiusm32rxf_model_insn_after (SIM_CPU *cpu, int last_p, int cycles)
229285612Sdelphij{
230285612Sdelphij  m32rbf_model_insn_after (cpu, last_p, cycles);
231285612Sdelphij}
232285612Sdelphij
233285612Sdelphijstatic INLINE void
23454359Srobertocheck_load_stall (SIM_CPU *cpu, int regno)
235132451Sroberto{
23654359Sroberto  UINT h_gr = CPU_M32R_MISC_PROFILE (cpu)->load_regs;
237289999Sglebius
238285612Sdelphij  if (regno != -1
23954359Sroberto      && (h_gr & (1 << regno)) != 0)
240285612Sdelphij    {
24154359Sroberto      CPU_M32R_MISC_PROFILE (cpu)->load_stall += 2;
242132451Sroberto      if (TRACE_INSN_P (cpu))
243285612Sdelphij	cgen_trace_printf (cpu, " ; Load stall of 2 cycles.");
244285612Sdelphij    }
245285612Sdelphij}
246285612Sdelphij
247285612Sdelphijint
248285612Sdelphijm32rxf_model_m32rx_u_exec (SIM_CPU *cpu, const IDESC *idesc,
249132451Sroberto			   int unit_num, int referenced,
25054359Sroberto			   INT sr, INT sr2, INT dr)
251132451Sroberto{
25256746Sroberto  check_load_stall (cpu, sr);
253285612Sdelphij  check_load_stall (cpu, sr2);
254285612Sdelphij  return idesc->timing->units[unit_num].done;
255285612Sdelphij}
256132451Sroberto
257132451Srobertoint
258132451Srobertom32rxf_model_m32rx_u_cmp (SIM_CPU *cpu, const IDESC *idesc,
259285612Sdelphij			   int unit_num, int referenced,
260132451Sroberto			   INT src1, INT src2)
261106163Sroberto{
262285612Sdelphij  check_load_stall (cpu, src1);
263200576Sroberto  check_load_stall (cpu, src2);
264285612Sdelphij  return idesc->timing->units[unit_num].done;
265285612Sdelphij}
266285612Sdelphij
267285612Sdelphijint
268285612Sdelphijm32rxf_model_m32rx_u_mac (SIM_CPU *cpu, const IDESC *idesc,
269200576Sroberto			   int unit_num, int referenced,
270285612Sdelphij			   INT src1, INT src2)
271285612Sdelphij{
272285612Sdelphij  check_load_stall (cpu, src1);
273200576Sroberto  check_load_stall (cpu, src2);
274132451Sroberto  return idesc->timing->units[unit_num].done;
275132451Sroberto}
276132451Sroberto
27782498Srobertoint
278285612Sdelphijm32rxf_model_m32rx_u_cti (SIM_CPU *cpu, const IDESC *idesc,
279285612Sdelphij			  int unit_num, int referenced,
280285612Sdelphij			  INT sr)
281285612Sdelphij{
282285612Sdelphij  PROFILE_DATA *profile = CPU_PROFILE_DATA (cpu);
283285612Sdelphij  int taken_p = (referenced & (1 << 1)) != 0;
28454359Sroberto
285285612Sdelphij  check_load_stall (cpu, sr);
286285612Sdelphij  if (taken_p)
287285612Sdelphij    {
288132451Sroberto      CPU_M32R_MISC_PROFILE (cpu)->cti_stall += 2;
289182007Sroberto      PROFILE_MODEL_TAKEN_COUNT (profile) += 1;
290182007Sroberto    }
291182007Sroberto  else
29254359Sroberto    PROFILE_MODEL_UNTAKEN_COUNT (profile) += 1;
293132451Sroberto  return idesc->timing->units[unit_num].done;
294182007Sroberto}
295285612Sdelphij
296285612Sdelphijint
29754359Srobertom32rxf_model_m32rx_u_load (SIM_CPU *cpu, const IDESC *idesc,
298200576Sroberto			   int unit_num, int referenced,
299289999Sglebius			   INT sr, INT dr)
300132451Sroberto{
301132451Sroberto  CPU_M32R_MISC_PROFILE (cpu)->load_regs_pending |= (1 << dr);
30254359Sroberto  return idesc->timing->units[unit_num].done;
303182007Sroberto}
30454359Sroberto
305132451Srobertoint
30654359Srobertom32rxf_model_m32rx_u_store (SIM_CPU *cpu, const IDESC *idesc,
30754359Sroberto			    int unit_num, int referenced,
308132451Sroberto			    INT src1, INT src2)
309285612Sdelphij{
31054359Sroberto  return idesc->timing->units[unit_num].done;
31154359Sroberto}
31254359Sroberto
31382498Sroberto#endif /* WITH_PROFILE_MODEL_P */
314285612Sdelphij