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