Home | History | Annotate | Line # | Download | only in m32r
m32r.c revision 1.8
      1 /* m32r simulator support code
      2    Copyright (C) 1996-2019 Free Software Foundation, Inc.
      3    Contributed by Cygnus Support.
      4 
      5    This file is part of GDB, the GNU debugger.
      6 
      7    This program is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3 of the License, or
     10    (at your option) any later version.
     11 
     12    This program is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19 
     20 #define WANT_CPU m32rbf
     21 #define WANT_CPU_M32RBF
     22 
     23 #include "sim-main.h"
     24 #include "cgen-mem.h"
     25 #include "cgen-ops.h"
     26 
     27 /* Decode gdb ctrl register number.  */
     28 
     29 int
     30 m32r_decode_gdb_ctrl_regnum (int gdb_regnum)
     31 {
     32   switch (gdb_regnum)
     33     {
     34       case PSW_REGNUM : return H_CR_PSW;
     35       case CBR_REGNUM : return H_CR_CBR;
     36       case SPI_REGNUM : return H_CR_SPI;
     37       case SPU_REGNUM : return H_CR_SPU;
     38       case BPC_REGNUM : return H_CR_BPC;
     39       case BBPSW_REGNUM : return H_CR_BBPSW;
     40       case BBPC_REGNUM : return H_CR_BBPC;
     41       case EVB_REGNUM : return H_CR_CR5;
     42     }
     43   abort ();
     44 }
     45 
     46 /* The contents of BUF are in target byte order.  */
     47 
     48 int
     49 m32rbf_fetch_register (SIM_CPU *current_cpu, int rn, unsigned char *buf, int len)
     50 {
     51   if (rn < 16)
     52     SETTWI (buf, m32rbf_h_gr_get (current_cpu, rn));
     53   else
     54     switch (rn)
     55       {
     56       case PSW_REGNUM :
     57       case CBR_REGNUM :
     58       case SPI_REGNUM :
     59       case SPU_REGNUM :
     60       case BPC_REGNUM :
     61       case BBPSW_REGNUM :
     62       case BBPC_REGNUM :
     63 	SETTWI (buf, m32rbf_h_cr_get (current_cpu,
     64 				      m32r_decode_gdb_ctrl_regnum (rn)));
     65 	break;
     66       case PC_REGNUM :
     67 	SETTWI (buf, m32rbf_h_pc_get (current_cpu));
     68 	break;
     69       case ACCL_REGNUM :
     70 	SETTWI (buf, GETLODI (m32rbf_h_accum_get (current_cpu)));
     71 	break;
     72       case ACCH_REGNUM :
     73 	SETTWI (buf, GETHIDI (m32rbf_h_accum_get (current_cpu)));
     74 	break;
     75       default :
     76 	return 0;
     77       }
     78 
     79   return -1; /*FIXME*/
     80 }
     81 
     82 /* The contents of BUF are in target byte order.  */
     83 
     84 int
     85 m32rbf_store_register (SIM_CPU *current_cpu, int rn, unsigned char *buf, int len)
     86 {
     87   if (rn < 16)
     88     m32rbf_h_gr_set (current_cpu, rn, GETTWI (buf));
     89   else
     90     switch (rn)
     91       {
     92       case PSW_REGNUM :
     93       case CBR_REGNUM :
     94       case SPI_REGNUM :
     95       case SPU_REGNUM :
     96       case BPC_REGNUM :
     97       case BBPSW_REGNUM :
     98       case BBPC_REGNUM :
     99 	m32rbf_h_cr_set (current_cpu,
    100 			 m32r_decode_gdb_ctrl_regnum (rn),
    101 			 GETTWI (buf));
    102 	break;
    103       case PC_REGNUM :
    104 	m32rbf_h_pc_set (current_cpu, GETTWI (buf));
    105 	break;
    106       case ACCL_REGNUM :
    107 	{
    108 	  DI val = m32rbf_h_accum_get (current_cpu);
    109 	  SETLODI (val, GETTWI (buf));
    110 	  m32rbf_h_accum_set (current_cpu, val);
    111 	  break;
    112 	}
    113       case ACCH_REGNUM :
    114 	{
    115 	  DI val = m32rbf_h_accum_get (current_cpu);
    116 	  SETHIDI (val, GETTWI (buf));
    117 	  m32rbf_h_accum_set (current_cpu, val);
    118 	  break;
    119 	}
    120       default :
    121 	return 0;
    122       }
    123 
    124   return -1; /*FIXME*/
    125 }
    126 
    127 USI
    129 m32rbf_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 
    163 void
    164 m32rbf_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 
    229 UQI
    230 m32rbf_h_psw_get_handler (SIM_CPU *current_cpu)
    231 {
    232   return (CPU (h_psw) & 0xfe) | (CPU (h_cond) & 1);
    233 }
    234 
    235 void
    236 m32rbf_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 
    244 DI
    245 m32rbf_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 
    264 void
    265 m32rbf_h_accum_set_handler (SIM_CPU *current_cpu, DI newval)
    266 {
    267   CPU (h_accum) = newval;
    268 }
    269 
    270 #if WITH_PROFILE_MODEL_P
    272 
    273 /* FIXME: Some of these should be inline or macros.  Later.  */
    274 
    275 /* Initialize cycle counting for an insn.
    276    FIRST_P is non-zero if this is the first insn in a set of parallel
    277    insns.  */
    278 
    279 void
    280 m32rbf_model_insn_before (SIM_CPU *cpu, int first_p)
    281 {
    282   M32R_MISC_PROFILE *mp = CPU_M32R_MISC_PROFILE (cpu);
    283   mp->cti_stall = 0;
    284   mp->load_stall = 0;
    285   if (first_p)
    286     {
    287       mp->load_regs_pending = 0;
    288       mp->biggest_cycles = 0;
    289     }
    290 }
    291 
    292 /* Record the cycles computed for an insn.
    293    LAST_P is non-zero if this is the last insn in a set of parallel insns,
    294    and we update the total cycle count.
    295    CYCLES is the cycle count of the insn.  */
    296 
    297 void
    298 m32rbf_model_insn_after (SIM_CPU *cpu, int last_p, int cycles)
    299 {
    300   PROFILE_DATA *p = CPU_PROFILE_DATA (cpu);
    301   M32R_MISC_PROFILE *mp = CPU_M32R_MISC_PROFILE (cpu);
    302   unsigned long total = cycles + mp->cti_stall + mp->load_stall;
    303 
    304   if (last_p)
    305     {
    306       unsigned long biggest = total > mp->biggest_cycles ? total : mp->biggest_cycles;
    307       PROFILE_MODEL_TOTAL_CYCLES (p) += biggest;
    308       PROFILE_MODEL_CUR_INSN_CYCLES (p) = total;
    309     }
    310   else
    311     {
    312       /* Here we take advantage of the fact that !last_p -> first_p.  */
    313       mp->biggest_cycles = total;
    314       PROFILE_MODEL_CUR_INSN_CYCLES (p) = total;
    315     }
    316 
    317   /* Branch and load stall counts are recorded independently of the
    318      total cycle count.  */
    319   PROFILE_MODEL_CTI_STALL_CYCLES (p) += mp->cti_stall;
    320   PROFILE_MODEL_LOAD_STALL_CYCLES (p) += mp->load_stall;
    321 
    322   mp->load_regs = mp->load_regs_pending;
    323 }
    324 
    325 static INLINE void
    326 check_load_stall (SIM_CPU *cpu, int regno)
    327 {
    328   UINT h_gr = CPU_M32R_MISC_PROFILE (cpu)->load_regs;
    329 
    330   if (regno != -1
    331       && (h_gr & (1 << regno)) != 0)
    332     {
    333       CPU_M32R_MISC_PROFILE (cpu)->load_stall += 2;
    334       if (TRACE_INSN_P (cpu))
    335 	cgen_trace_printf (cpu, " ; Load stall of 2 cycles.");
    336     }
    337 }
    338 
    339 int
    340 m32rbf_model_m32r_d_u_exec (SIM_CPU *cpu, const IDESC *idesc,
    341 			    int unit_num, int referenced,
    342 			    INT sr, INT sr2, INT dr)
    343 {
    344   check_load_stall (cpu, sr);
    345   check_load_stall (cpu, sr2);
    346   return idesc->timing->units[unit_num].done;
    347 }
    348 
    349 int
    350 m32rbf_model_m32r_d_u_cmp (SIM_CPU *cpu, const IDESC *idesc,
    351 			   int unit_num, int referenced,
    352 			   INT src1, INT src2)
    353 {
    354   check_load_stall (cpu, src1);
    355   check_load_stall (cpu, src2);
    356   return idesc->timing->units[unit_num].done;
    357 }
    358 
    359 int
    360 m32rbf_model_m32r_d_u_mac (SIM_CPU *cpu, const IDESC *idesc,
    361 			   int unit_num, int referenced,
    362 			   INT src1, INT src2)
    363 {
    364   check_load_stall (cpu, src1);
    365   check_load_stall (cpu, src2);
    366   return idesc->timing->units[unit_num].done;
    367 }
    368 
    369 int
    370 m32rbf_model_m32r_d_u_cti (SIM_CPU *cpu, const IDESC *idesc,
    371 			   int unit_num, int referenced,
    372 			   INT sr)
    373 {
    374   PROFILE_DATA *profile = CPU_PROFILE_DATA (cpu);
    375   int taken_p = (referenced & (1 << 1)) != 0;
    376 
    377   check_load_stall (cpu, sr);
    378   if (taken_p)
    379     {
    380       CPU_M32R_MISC_PROFILE (cpu)->cti_stall += 2;
    381       PROFILE_MODEL_TAKEN_COUNT (profile) += 1;
    382     }
    383   else
    384     PROFILE_MODEL_UNTAKEN_COUNT (profile) += 1;
    385   return idesc->timing->units[unit_num].done;
    386 }
    387 
    388 int
    389 m32rbf_model_m32r_d_u_load (SIM_CPU *cpu, const IDESC *idesc,
    390 			    int unit_num, int referenced,
    391 			    INT sr, INT dr)
    392 {
    393   CPU_M32R_MISC_PROFILE (cpu)->load_regs_pending |= (1 << dr);
    394   check_load_stall (cpu, sr);
    395   return idesc->timing->units[unit_num].done;
    396 }
    397 
    398 int
    399 m32rbf_model_m32r_d_u_store (SIM_CPU *cpu, const IDESC *idesc,
    400 			     int unit_num, int referenced,
    401 			     INT src1, INT src2)
    402 {
    403   check_load_stall (cpu, src1);
    404   check_load_stall (cpu, src2);
    405   return idesc->timing->units[unit_num].done;
    406 }
    407 
    408 int
    409 m32rbf_model_test_u_exec (SIM_CPU *cpu, const IDESC *idesc,
    410 			  int unit_num, int referenced)
    411 {
    412   return idesc->timing->units[unit_num].done;
    413 }
    414 
    415 #endif /* WITH_PROFILE_MODEL_P */
    416