1/* m32r simulator support code
2   Copyright (C) 1996, 1997, 1998, 2003, 2007, 2008, 2009, 2010, 2011
3   Free Software Foundation, Inc.
4   Contributed by Cygnus Support.
5
6   This file is part of GDB, the GNU debugger.
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21#define WANT_CPU m32rbf
22#define WANT_CPU_M32RBF
23
24#include "sim-main.h"
25#include "cgen-mem.h"
26#include "cgen-ops.h"
27
28/* Decode gdb ctrl register number.  */
29
30int
31m32r_decode_gdb_ctrl_regnum (int gdb_regnum)
32{
33  switch (gdb_regnum)
34    {
35      case PSW_REGNUM : return H_CR_PSW;
36      case CBR_REGNUM : return H_CR_CBR;
37      case SPI_REGNUM : return H_CR_SPI;
38      case SPU_REGNUM : return H_CR_SPU;
39      case BPC_REGNUM : return H_CR_BPC;
40      case BBPSW_REGNUM : return H_CR_BBPSW;
41      case BBPC_REGNUM : return H_CR_BBPC;
42      case EVB_REGNUM : return H_CR_CR5;
43    }
44  abort ();
45}
46
47/* The contents of BUF are in target byte order.  */
48
49int
50m32rbf_fetch_register (SIM_CPU *current_cpu, int rn, unsigned char *buf, int len)
51{
52  if (rn < 16)
53    SETTWI (buf, m32rbf_h_gr_get (current_cpu, rn));
54  else
55    switch (rn)
56      {
57      case PSW_REGNUM :
58      case CBR_REGNUM :
59      case SPI_REGNUM :
60      case SPU_REGNUM :
61      case BPC_REGNUM :
62      case BBPSW_REGNUM :
63      case BBPC_REGNUM :
64	SETTWI (buf, m32rbf_h_cr_get (current_cpu,
65				      m32r_decode_gdb_ctrl_regnum (rn)));
66	break;
67      case PC_REGNUM :
68	SETTWI (buf, m32rbf_h_pc_get (current_cpu));
69	break;
70      case ACCL_REGNUM :
71	SETTWI (buf, GETLODI (m32rbf_h_accum_get (current_cpu)));
72	break;
73      case ACCH_REGNUM :
74	SETTWI (buf, GETHIDI (m32rbf_h_accum_get (current_cpu)));
75	break;
76      default :
77	return 0;
78      }
79
80  return -1; /*FIXME*/
81}
82
83/* The contents of BUF are in target byte order.  */
84
85int
86m32rbf_store_register (SIM_CPU *current_cpu, int rn, unsigned char *buf, int len)
87{
88  if (rn < 16)
89    m32rbf_h_gr_set (current_cpu, rn, GETTWI (buf));
90  else
91    switch (rn)
92      {
93      case PSW_REGNUM :
94      case CBR_REGNUM :
95      case SPI_REGNUM :
96      case SPU_REGNUM :
97      case BPC_REGNUM :
98      case BBPSW_REGNUM :
99      case BBPC_REGNUM :
100	m32rbf_h_cr_set (current_cpu,
101			 m32r_decode_gdb_ctrl_regnum (rn),
102			 GETTWI (buf));
103	break;
104      case PC_REGNUM :
105	m32rbf_h_pc_set (current_cpu, GETTWI (buf));
106	break;
107      case ACCL_REGNUM :
108	{
109	  DI val = m32rbf_h_accum_get (current_cpu);
110	  SETLODI (val, GETTWI (buf));
111	  m32rbf_h_accum_set (current_cpu, val);
112	  break;
113	}
114      case ACCH_REGNUM :
115	{
116	  DI val = m32rbf_h_accum_get (current_cpu);
117	  SETHIDI (val, GETTWI (buf));
118	  m32rbf_h_accum_set (current_cpu, val);
119	  break;
120	}
121      default :
122	return 0;
123      }
124
125  return -1; /*FIXME*/
126}
127
128USI
129m32rbf_h_cr_get_handler (SIM_CPU *current_cpu, UINT cr)
130{
131  switch (cr)
132    {
133    case H_CR_PSW : /* psw */
134      return (((CPU (h_bpsw) & 0xc1) << 8)
135	      | ((CPU (h_psw) & 0xc0) << 0)
136	      | GET_H_COND ());
137    case H_CR_BBPSW : /* backup backup psw */
138      return CPU (h_bbpsw) & 0xc1;
139    case H_CR_CBR : /* condition bit */
140      return GET_H_COND ();
141    case H_CR_SPI : /* interrupt stack pointer */
142      if (! GET_H_SM ())
143	return CPU (h_gr[H_GR_SP]);
144      else
145	return CPU (h_cr[H_CR_SPI]);
146    case H_CR_SPU : /* user stack pointer */
147      if (GET_H_SM ())
148	return CPU (h_gr[H_GR_SP]);
149      else
150	return CPU (h_cr[H_CR_SPU]);
151    case H_CR_BPC : /* backup pc */
152      return CPU (h_cr[H_CR_BPC]) & 0xfffffffe;
153    case H_CR_BBPC : /* backup backup pc */
154      return CPU (h_cr[H_CR_BBPC]) & 0xfffffffe;
155    case 4 : /* ??? unspecified, but apparently available */
156    case 5 : /* ??? unspecified, but apparently available */
157      return CPU (h_cr[cr]);
158    default :
159      return 0;
160    }
161}
162
163void
164m32rbf_h_cr_set_handler (SIM_CPU *current_cpu, UINT cr, USI newval)
165{
166  switch (cr)
167    {
168    case H_CR_PSW : /* psw */
169      {
170	int old_sm = (CPU (h_psw) & 0x80) != 0;
171	int new_sm = (newval & 0x80) != 0;
172	CPU (h_bpsw) = (newval >> 8) & 0xff;
173	CPU (h_psw) = newval & 0xff;
174	SET_H_COND (newval & 1);
175	/* When switching stack modes, update the registers.  */
176	if (old_sm != new_sm)
177	  {
178	    if (old_sm)
179	      {
180		/* Switching user -> system.  */
181		CPU (h_cr[H_CR_SPU]) = CPU (h_gr[H_GR_SP]);
182		CPU (h_gr[H_GR_SP]) = CPU (h_cr[H_CR_SPI]);
183	      }
184	    else
185	      {
186		/* Switching system -> user.  */
187		CPU (h_cr[H_CR_SPI]) = CPU (h_gr[H_GR_SP]);
188		CPU (h_gr[H_GR_SP]) = CPU (h_cr[H_CR_SPU]);
189	      }
190	  }
191	break;
192      }
193    case H_CR_BBPSW : /* backup backup psw */
194      CPU (h_bbpsw) = newval & 0xff;
195      break;
196    case H_CR_CBR : /* condition bit */
197      SET_H_COND (newval & 1);
198      break;
199    case H_CR_SPI : /* interrupt stack pointer */
200      if (! GET_H_SM ())
201	CPU (h_gr[H_GR_SP]) = newval;
202      else
203	CPU (h_cr[H_CR_SPI]) = newval;
204      break;
205    case H_CR_SPU : /* user stack pointer */
206      if (GET_H_SM ())
207	CPU (h_gr[H_GR_SP]) = newval;
208      else
209	CPU (h_cr[H_CR_SPU]) = newval;
210      break;
211    case H_CR_BPC : /* backup pc */
212      CPU (h_cr[H_CR_BPC]) = newval;
213      break;
214    case H_CR_BBPC : /* backup backup pc */
215      CPU (h_cr[H_CR_BBPC]) = newval;
216      break;
217    case 4 : /* ??? unspecified, but apparently available */
218    case 5 : /* ??? unspecified, but apparently available */
219      CPU (h_cr[cr]) = newval;
220      break;
221    default :
222      /* ignore */
223      break;
224    }
225}
226
227/* Cover fns to access h-psw.  */
228
229UQI
230m32rbf_h_psw_get_handler (SIM_CPU *current_cpu)
231{
232  return (CPU (h_psw) & 0xfe) | (CPU (h_cond) & 1);
233}
234
235void
236m32rbf_h_psw_set_handler (SIM_CPU *current_cpu, UQI newval)
237{
238  CPU (h_psw) = newval;
239  CPU (h_cond) = newval & 1;
240}
241
242/* Cover fns to access h-accum.  */
243
244DI
245m32rbf_h_accum_get_handler (SIM_CPU *current_cpu)
246{
247  /* Sign extend the top 8 bits.  */
248  DI r;
249#if 1
250  r = ANDDI (CPU (h_accum), MAKEDI (0xffffff, 0xffffffff));
251  r = XORDI (r, MAKEDI (0x800000, 0));
252  r = SUBDI (r, MAKEDI (0x800000, 0));
253#else
254  SI hi,lo;
255  r = CPU (h_accum);
256  hi = GETHIDI (r);
257  lo = GETLODI (r);
258  hi = ((hi & 0xffffff) ^ 0x800000) - 0x800000;
259  r = MAKEDI (hi, lo);
260#endif
261  return r;
262}
263
264void
265m32rbf_h_accum_set_handler (SIM_CPU *current_cpu, DI newval)
266{
267  CPU (h_accum) = newval;
268}
269
270#if WITH_PROFILE_MODEL_P
271
272/* FIXME: Some of these should be inline or macros.  Later.  */
273
274/* Initialize cycle counting for an insn.
275   FIRST_P is non-zero if this is the first insn in a set of parallel
276   insns.  */
277
278void
279m32rbf_model_insn_before (SIM_CPU *cpu, int first_p)
280{
281  M32R_MISC_PROFILE *mp = CPU_M32R_MISC_PROFILE (cpu);
282  mp->cti_stall = 0;
283  mp->load_stall = 0;
284  if (first_p)
285    {
286      mp->load_regs_pending = 0;
287      mp->biggest_cycles = 0;
288    }
289}
290
291/* Record the cycles computed for an insn.
292   LAST_P is non-zero if this is the last insn in a set of parallel insns,
293   and we update the total cycle count.
294   CYCLES is the cycle count of the insn.  */
295
296void
297m32rbf_model_insn_after (SIM_CPU *cpu, int last_p, int cycles)
298{
299  PROFILE_DATA *p = CPU_PROFILE_DATA (cpu);
300  M32R_MISC_PROFILE *mp = CPU_M32R_MISC_PROFILE (cpu);
301  unsigned long total = cycles + mp->cti_stall + mp->load_stall;
302
303  if (last_p)
304    {
305      unsigned long biggest = total > mp->biggest_cycles ? total : mp->biggest_cycles;
306      PROFILE_MODEL_TOTAL_CYCLES (p) += biggest;
307      PROFILE_MODEL_CUR_INSN_CYCLES (p) = total;
308    }
309  else
310    {
311      /* Here we take advantage of the fact that !last_p -> first_p.  */
312      mp->biggest_cycles = total;
313      PROFILE_MODEL_CUR_INSN_CYCLES (p) = total;
314    }
315
316  /* Branch and load stall counts are recorded independently of the
317     total cycle count.  */
318  PROFILE_MODEL_CTI_STALL_CYCLES (p) += mp->cti_stall;
319  PROFILE_MODEL_LOAD_STALL_CYCLES (p) += mp->load_stall;
320
321  mp->load_regs = mp->load_regs_pending;
322}
323
324static INLINE void
325check_load_stall (SIM_CPU *cpu, int regno)
326{
327  UINT h_gr = CPU_M32R_MISC_PROFILE (cpu)->load_regs;
328
329  if (regno != -1
330      && (h_gr & (1 << regno)) != 0)
331    {
332      CPU_M32R_MISC_PROFILE (cpu)->load_stall += 2;
333      if (TRACE_INSN_P (cpu))
334	cgen_trace_printf (cpu, " ; Load stall of 2 cycles.");
335    }
336}
337
338int
339m32rbf_model_m32r_d_u_exec (SIM_CPU *cpu, const IDESC *idesc,
340			    int unit_num, int referenced,
341			    INT sr, INT sr2, INT dr)
342{
343  check_load_stall (cpu, sr);
344  check_load_stall (cpu, sr2);
345  return idesc->timing->units[unit_num].done;
346}
347
348int
349m32rbf_model_m32r_d_u_cmp (SIM_CPU *cpu, const IDESC *idesc,
350			   int unit_num, int referenced,
351			   INT src1, INT src2)
352{
353  check_load_stall (cpu, src1);
354  check_load_stall (cpu, src2);
355  return idesc->timing->units[unit_num].done;
356}
357
358int
359m32rbf_model_m32r_d_u_mac (SIM_CPU *cpu, const IDESC *idesc,
360			   int unit_num, int referenced,
361			   INT src1, INT src2)
362{
363  check_load_stall (cpu, src1);
364  check_load_stall (cpu, src2);
365  return idesc->timing->units[unit_num].done;
366}
367
368int
369m32rbf_model_m32r_d_u_cti (SIM_CPU *cpu, const IDESC *idesc,
370			   int unit_num, int referenced,
371			   INT sr)
372{
373  PROFILE_DATA *profile = CPU_PROFILE_DATA (cpu);
374  int taken_p = (referenced & (1 << 1)) != 0;
375
376  check_load_stall (cpu, sr);
377  if (taken_p)
378    {
379      CPU_M32R_MISC_PROFILE (cpu)->cti_stall += 2;
380      PROFILE_MODEL_TAKEN_COUNT (profile) += 1;
381    }
382  else
383    PROFILE_MODEL_UNTAKEN_COUNT (profile) += 1;
384  return idesc->timing->units[unit_num].done;
385}
386
387int
388m32rbf_model_m32r_d_u_load (SIM_CPU *cpu, const IDESC *idesc,
389			    int unit_num, int referenced,
390			    INT sr, INT dr)
391{
392  CPU_M32R_MISC_PROFILE (cpu)->load_regs_pending |= (1 << dr);
393  check_load_stall (cpu, sr);
394  return idesc->timing->units[unit_num].done;
395}
396
397int
398m32rbf_model_m32r_d_u_store (SIM_CPU *cpu, const IDESC *idesc,
399			     int unit_num, int referenced,
400			     INT src1, INT src2)
401{
402  check_load_stall (cpu, src1);
403  check_load_stall (cpu, src2);
404  return idesc->timing->units[unit_num].done;
405}
406
407int
408m32rbf_model_test_u_exec (SIM_CPU *cpu, const IDESC *idesc,
409			  int unit_num, int referenced)
410{
411  return idesc->timing->units[unit_num].done;
412}
413
414#endif /* WITH_PROFILE_MODEL_P */
415