Home | History | Annotate | Line # | Download | only in cris
crisv32f.c revision 1.1
      1  1.1  christos /* CRIS v32 simulator support code
      2  1.1  christos    Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
      3  1.1  christos    Free Software Foundation, Inc.
      4  1.1  christos    Contributed by Axis Communications.
      5  1.1  christos 
      6  1.1  christos This file is part of the GNU simulators.
      7  1.1  christos 
      8  1.1  christos This program is free software; you can redistribute it and/or modify
      9  1.1  christos it under the terms of the GNU General Public License as published by
     10  1.1  christos the Free Software Foundation; either version 3 of the License, or
     11  1.1  christos (at your option) any later version.
     12  1.1  christos 
     13  1.1  christos This program is distributed in the hope that it will be useful,
     14  1.1  christos but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  1.1  christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  1.1  christos GNU General Public License for more details.
     17  1.1  christos 
     18  1.1  christos You should have received a copy of the GNU General Public License
     19  1.1  christos along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     20  1.1  christos 
     21  1.1  christos /* The infrastructure is based on that of i960.c.  */
     22  1.1  christos 
     23  1.1  christos #define WANT_CPU_CRISV32F
     24  1.1  christos 
     25  1.1  christos #define SPECIFIC_U_EXEC_FN
     26  1.1  christos #define SPECIFIC_U_SKIP4_FN
     27  1.1  christos #define SPECIFIC_U_CONST16_FN
     28  1.1  christos #define SPECIFIC_U_CONST32_FN
     29  1.1  christos #define SPECIFIC_U_MEM_FN
     30  1.1  christos #define SPECIFIC_U_MOVEM_FN
     31  1.1  christos #define BASENUM 32
     32  1.1  christos #define CRIS_TLS_REGISTER 2
     33  1.1  christos #include "cris-tmpl.c"
     34  1.1  christos 
     35  1.1  christos #if WITH_PROFILE_MODEL_P
     36  1.1  christos 
     37  1.1  christos /* Re-use the bit position for the BZ register, since there are no stall
     38  1.1  christos    cycles for reading or writing it.  */
     39  1.1  christos #define CRIS_BZ_REGNO 16
     40  1.1  christos #define CRIS_MODF_JUMP_MASK (1 << CRIS_BZ_REGNO)
     41  1.1  christos /* Likewise for the WZ register, marking memory writes.  */
     42  1.1  christos #define CRIS_WZ_REGNO 20
     43  1.1  christos #define CRIS_MODF_MEM_WRITE_MASK (1 << CRIS_WZ_REGNO)
     44  1.1  christos #define CRIS_MOF_REGNO (16 + 7)
     45  1.1  christos #define CRIS_ALWAYS_CONDITION 14
     46  1.1  christos 
     47  1.1  christos /* This macro must only be used in context where there's only one
     48  1.1  christos    dynamic cause for a penalty, except in the u-exec unit.  */
     49  1.1  christos 
     50  1.1  christos #define PENALIZE1(CNT)					\
     51  1.1  christos   do							\
     52  1.1  christos     {							\
     53  1.1  christos       CPU_CRIS_MISC_PROFILE (current_cpu)->CNT++;	\
     54  1.1  christos       model_data->prev_prev_prev_modf_regs		\
     55  1.1  christos 	= model_data->prev_prev_modf_regs;		\
     56  1.1  christos       model_data->prev_prev_modf_regs			\
     57  1.1  christos 	= model_data->prev_modf_regs;			\
     58  1.1  christos       model_data->prev_modf_regs = 0;			\
     59  1.1  christos       model_data->prev_prev_prev_movem_dest_regs	\
     60  1.1  christos 	= model_data->prev_prev_movem_dest_regs;	\
     61  1.1  christos       model_data->prev_prev_movem_dest_regs		\
     62  1.1  christos 	= model_data->prev_movem_dest_regs;		\
     63  1.1  christos       model_data->prev_movem_dest_regs = 0;		\
     64  1.1  christos     }							\
     65  1.1  christos   while (0)
     66  1.1  christos 
     67  1.1  christos 
     68  1.1  christos /* Model function for u-skip4 unit.  */
     69  1.1  christos 
     70  1.1  christos int
     71  1.1  christos MY (XCONCAT3 (f_model_crisv,BASENUM,
     72  1.1  christos 	      _u_skip4)) (SIM_CPU *current_cpu,
     73  1.1  christos 			  const IDESC *idesc ATTRIBUTE_UNUSED,
     74  1.1  christos 			  int unit_num ATTRIBUTE_UNUSED,
     75  1.1  christos 			  int referenced ATTRIBUTE_UNUSED)
     76  1.1  christos {
     77  1.1  christos   /* Handle PC not being updated with pbb.  FIXME: What if not pbb?  */
     78  1.1  christos   CPU (h_pc) += 4;
     79  1.1  christos   return 0;
     80  1.1  christos }
     81  1.1  christos 
     82  1.1  christos /* Model function for u-exec unit.  */
     83  1.1  christos 
     84  1.1  christos int
     85  1.1  christos MY (XCONCAT3 (f_model_crisv,BASENUM,
     86  1.1  christos 	      _u_exec)) (SIM_CPU *current_cpu,
     87  1.1  christos 			 const IDESC *idesc ATTRIBUTE_UNUSED,
     88  1.1  christos 			 int unit_num ATTRIBUTE_UNUSED,
     89  1.1  christos 			 int referenced ATTRIBUTE_UNUSED,
     90  1.1  christos 			 INT destreg_in,
     91  1.1  christos 			 INT srcreg,
     92  1.1  christos 			 INT destreg_out)
     93  1.1  christos {
     94  1.1  christos   MODEL_CRISV32_DATA *model_data
     95  1.1  christos     = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
     96  1.1  christos   UINT modf_regs
     97  1.1  christos     = ((destreg_out == -1 ? 0 : (1 << destreg_out))
     98  1.1  christos        | model_data->modf_regs);
     99  1.1  christos 
    100  1.1  christos   if (srcreg != -1)
    101  1.1  christos     {
    102  1.1  christos       if (model_data->prev_movem_dest_regs & (1 << srcreg))
    103  1.1  christos 	{
    104  1.1  christos 	  PENALIZE1 (movemdst_stall_count);
    105  1.1  christos 	  PENALIZE1 (movemdst_stall_count);
    106  1.1  christos 	  PENALIZE1 (movemdst_stall_count);
    107  1.1  christos 	}
    108  1.1  christos       else if (model_data->prev_prev_movem_dest_regs & (1 << srcreg))
    109  1.1  christos 	{
    110  1.1  christos 	  PENALIZE1 (movemdst_stall_count);
    111  1.1  christos 	  PENALIZE1 (movemdst_stall_count);
    112  1.1  christos 	}
    113  1.1  christos       else if (model_data->prev_prev_prev_movem_dest_regs & (1 << srcreg))
    114  1.1  christos 	PENALIZE1 (movemdst_stall_count);
    115  1.1  christos     }
    116  1.1  christos 
    117  1.1  christos   if (destreg_in != -1)
    118  1.1  christos     {
    119  1.1  christos       if (model_data->prev_movem_dest_regs & (1 << destreg_in))
    120  1.1  christos 	{
    121  1.1  christos 	  PENALIZE1 (movemdst_stall_count);
    122  1.1  christos 	  PENALIZE1 (movemdst_stall_count);
    123  1.1  christos 	  PENALIZE1 (movemdst_stall_count);
    124  1.1  christos 	}
    125  1.1  christos       else if (model_data->prev_prev_movem_dest_regs & (1 << destreg_in))
    126  1.1  christos 	{
    127  1.1  christos 	  PENALIZE1 (movemdst_stall_count);
    128  1.1  christos 	  PENALIZE1 (movemdst_stall_count);
    129  1.1  christos 	}
    130  1.1  christos       else if (model_data->prev_prev_prev_movem_dest_regs & (1 << destreg_in))
    131  1.1  christos 	PENALIZE1 (movemdst_stall_count);
    132  1.1  christos     }
    133  1.1  christos 
    134  1.1  christos   model_data->prev_prev_prev_modf_regs
    135  1.1  christos     = model_data->prev_prev_modf_regs;
    136  1.1  christos   model_data->prev_prev_modf_regs = model_data->prev_modf_regs;
    137  1.1  christos   model_data->prev_modf_regs = modf_regs;
    138  1.1  christos   model_data->modf_regs = 0;
    139  1.1  christos 
    140  1.1  christos   model_data->prev_prev_prev_movem_dest_regs
    141  1.1  christos     = model_data->prev_prev_movem_dest_regs;
    142  1.1  christos   model_data->prev_prev_movem_dest_regs = model_data->prev_movem_dest_regs;
    143  1.1  christos   model_data->prev_movem_dest_regs = model_data->movem_dest_regs;
    144  1.1  christos   model_data->movem_dest_regs = 0;
    145  1.1  christos 
    146  1.1  christos   /* Handle PC not being updated with pbb.  FIXME: What if not pbb?  */
    147  1.1  christos   CPU (h_pc) += 2;
    148  1.1  christos   return 1;
    149  1.1  christos }
    150  1.1  christos 
    151  1.1  christos /* Special case used when the destination is a special register.  */
    152  1.1  christos 
    153  1.1  christos int
    154  1.1  christos MY (XCONCAT3 (f_model_crisv,BASENUM,
    155  1.1  christos 	      _u_exec_to_sr)) (SIM_CPU *current_cpu,
    156  1.1  christos 			       const IDESC *idesc ATTRIBUTE_UNUSED,
    157  1.1  christos 			       int unit_num ATTRIBUTE_UNUSED,
    158  1.1  christos 			       int referenced ATTRIBUTE_UNUSED,
    159  1.1  christos 			       INT srcreg,
    160  1.1  christos 			       INT specreg)
    161  1.1  christos {
    162  1.1  christos   int specdest;
    163  1.1  christos 
    164  1.1  christos   if (specreg != -1)
    165  1.1  christos     specdest = specreg + 16;
    166  1.1  christos   else
    167  1.1  christos     abort ();
    168  1.1  christos 
    169  1.1  christos   return MY (XCONCAT3 (f_model_crisv,BASENUM,_u_exec))
    170  1.1  christos     (current_cpu, NULL, 0, 0, -1, srcreg,
    171  1.1  christos      /* The positions for constant-zero registers BZ and WZ are recycled
    172  1.1  christos 	for jump and memory-write markers.  We must take precautions
    173  1.1  christos 	here not to add false markers for them.  It might be that the
    174  1.1  christos 	hardware inserts stall cycles for instructions that actually try
    175  1.1  christos 	and write those registers, but we'll burn that bridge when we
    176  1.1  christos 	get to it; we'd have to find other free bits or make new
    177  1.1  christos 	model_data variables.  However, it's doubtful that there will
    178  1.1  christos 	ever be a need to be cycle-correct for useless code, at least in
    179  1.1  christos 	this particular simulator, mainly used for GCC testing.  */
    180  1.1  christos      specdest == CRIS_BZ_REGNO || specdest == CRIS_WZ_REGNO
    181  1.1  christos      ? -1 : specdest);
    182  1.1  christos }
    183  1.1  christos 
    184  1.1  christos 
    185  1.1  christos /* Special case for movem.  */
    186  1.1  christos 
    187  1.1  christos int
    188  1.1  christos MY (XCONCAT3 (f_model_crisv,BASENUM,
    189  1.1  christos 	      _u_exec_movem)) (SIM_CPU *current_cpu,
    190  1.1  christos 			       const IDESC *idesc ATTRIBUTE_UNUSED,
    191  1.1  christos 			       int unit_num ATTRIBUTE_UNUSED,
    192  1.1  christos 			       int referenced ATTRIBUTE_UNUSED,
    193  1.1  christos 			       INT srcreg,
    194  1.1  christos 			       INT destreg_out)
    195  1.1  christos {
    196  1.1  christos   return MY (XCONCAT3 (f_model_crisv,BASENUM,_u_exec))
    197  1.1  christos     (current_cpu, NULL, 0, 0, -1, srcreg, destreg_out);
    198  1.1  christos }
    199  1.1  christos 
    200  1.1  christos /* Model function for u-const16 unit.  */
    201  1.1  christos 
    202  1.1  christos int
    203  1.1  christos MY (XCONCAT3 (f_model_crisv,BASENUM,
    204  1.1  christos 	      _u_const16)) (SIM_CPU *current_cpu,
    205  1.1  christos 			    const IDESC *idesc ATTRIBUTE_UNUSED,
    206  1.1  christos 			    int unit_num ATTRIBUTE_UNUSED,
    207  1.1  christos 			    int referenced ATTRIBUTE_UNUSED)
    208  1.1  christos {
    209  1.1  christos   MODEL_CRISV32_DATA *model_data
    210  1.1  christos     = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
    211  1.1  christos 
    212  1.1  christos   /* If the previous insn was a jump of some sort and this insn
    213  1.1  christos      straddles a cache-line, there's a one-cycle penalty.
    214  1.1  christos      FIXME: Test-cases for normal const16 and others, like branch.  */
    215  1.1  christos   if ((model_data->prev_modf_regs & CRIS_MODF_JUMP_MASK)
    216  1.1  christos       && (CPU (h_pc) & 0x1e) == 0x1e)
    217  1.1  christos     PENALIZE1 (jumptarget_stall_count);
    218  1.1  christos 
    219  1.1  christos   /* Handle PC not being updated with pbb.  FIXME: What if not pbb?  */
    220  1.1  christos   CPU (h_pc) += 2;
    221  1.1  christos 
    222  1.1  christos   return 0;
    223  1.1  christos }
    224  1.1  christos 
    225  1.1  christos /* Model function for u-const32 unit.  */
    226  1.1  christos 
    227  1.1  christos int
    228  1.1  christos MY (XCONCAT3 (f_model_crisv,BASENUM,
    229  1.1  christos 	      _u_const32)) (SIM_CPU *current_cpu,
    230  1.1  christos 			    const IDESC *idesc ATTRIBUTE_UNUSED,
    231  1.1  christos 			    int unit_num ATTRIBUTE_UNUSED,
    232  1.1  christos 			    int referenced ATTRIBUTE_UNUSED)
    233  1.1  christos {
    234  1.1  christos   MODEL_CRISV32_DATA *model_data
    235  1.1  christos     = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
    236  1.1  christos 
    237  1.1  christos   /* If the previous insn was a jump of some sort and this insn
    238  1.1  christos      straddles a cache-line, there's a one-cycle penalty.  */
    239  1.1  christos   if ((model_data->prev_modf_regs & CRIS_MODF_JUMP_MASK)
    240  1.1  christos       && (CPU (h_pc) & 0x1e) == 0x1c)
    241  1.1  christos     PENALIZE1 (jumptarget_stall_count);
    242  1.1  christos 
    243  1.1  christos   /* Handle PC not being updated with pbb.  FIXME: What if not pbb?  */
    244  1.1  christos   CPU (h_pc) += 4;
    245  1.1  christos 
    246  1.1  christos   return 0;
    247  1.1  christos }
    248  1.1  christos 
    249  1.1  christos /* Model function for u-mem unit.  */
    250  1.1  christos 
    251  1.1  christos int
    252  1.1  christos MY (XCONCAT3 (f_model_crisv,BASENUM,
    253  1.1  christos 	      _u_mem)) (SIM_CPU *current_cpu,
    254  1.1  christos 			const IDESC *idesc ATTRIBUTE_UNUSED,
    255  1.1  christos 			int unit_num ATTRIBUTE_UNUSED,
    256  1.1  christos 			int referenced ATTRIBUTE_UNUSED,
    257  1.1  christos 			INT srcreg)
    258  1.1  christos {
    259  1.1  christos   MODEL_CRISV32_DATA *model_data
    260  1.1  christos     = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
    261  1.1  christos 
    262  1.1  christos   if (srcreg == -1)
    263  1.1  christos     abort ();
    264  1.1  christos 
    265  1.1  christos   /* If srcreg references a register modified in the previous cycle
    266  1.1  christos      through other than autoincrement, then there's a penalty: one
    267  1.1  christos      cycle.  */
    268  1.1  christos   if (model_data->prev_modf_regs & (1 << srcreg))
    269  1.1  christos     PENALIZE1 (memsrc_stall_count);
    270  1.1  christos 
    271  1.1  christos   return 0;
    272  1.1  christos }
    273  1.1  christos 
    274  1.1  christos /* Model function for u-mem-r unit.  */
    275  1.1  christos 
    276  1.1  christos int
    277  1.1  christos MY (XCONCAT3 (f_model_crisv,BASENUM,
    278  1.1  christos 	      _u_mem_r)) (SIM_CPU *current_cpu,
    279  1.1  christos 			  const IDESC *idesc ATTRIBUTE_UNUSED,
    280  1.1  christos 			  int unit_num ATTRIBUTE_UNUSED,
    281  1.1  christos 			  int referenced ATTRIBUTE_UNUSED)
    282  1.1  christos {
    283  1.1  christos   MODEL_CRISV32_DATA *model_data
    284  1.1  christos     = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
    285  1.1  christos 
    286  1.1  christos   /* There's a two-cycle penalty for read after a memory write in any of
    287  1.1  christos      the two previous cycles, known as a cache read-after-write hazard.
    288  1.1  christos 
    289  1.1  christos      This model function (the model_data member access) depends on being
    290  1.1  christos      executed before the u-exec unit.  */
    291  1.1  christos   if ((model_data->prev_modf_regs & CRIS_MODF_MEM_WRITE_MASK)
    292  1.1  christos       || (model_data->prev_prev_modf_regs & CRIS_MODF_MEM_WRITE_MASK))
    293  1.1  christos     {
    294  1.1  christos       PENALIZE1 (memraw_stall_count);
    295  1.1  christos       PENALIZE1 (memraw_stall_count);
    296  1.1  christos     }
    297  1.1  christos 
    298  1.1  christos   return 0;
    299  1.1  christos }
    300  1.1  christos 
    301  1.1  christos /* Model function for u-mem-w unit.  */
    302  1.1  christos 
    303  1.1  christos int
    304  1.1  christos MY (XCONCAT3 (f_model_crisv,BASENUM,
    305  1.1  christos 	      _u_mem_w)) (SIM_CPU *current_cpu,
    306  1.1  christos 			  const IDESC *idesc ATTRIBUTE_UNUSED,
    307  1.1  christos 			  int unit_num ATTRIBUTE_UNUSED,
    308  1.1  christos 			  int referenced ATTRIBUTE_UNUSED)
    309  1.1  christos {
    310  1.1  christos   MODEL_CRISV32_DATA *model_data
    311  1.1  christos     = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
    312  1.1  christos 
    313  1.1  christos   /* Mark that memory has been written.  This model function (the
    314  1.1  christos      model_data member access) depends on being executed after the
    315  1.1  christos      u-exec unit.  */
    316  1.1  christos   model_data->prev_modf_regs |= CRIS_MODF_MEM_WRITE_MASK;
    317  1.1  christos 
    318  1.1  christos   return 0;
    319  1.1  christos }
    320  1.1  christos 
    321  1.1  christos /* Model function for u-movem-rtom unit.  */
    322  1.1  christos 
    323  1.1  christos int
    324  1.1  christos MY (XCONCAT3 (f_model_crisv,BASENUM,
    325  1.1  christos 	      _u_movem_rtom)) (SIM_CPU *current_cpu,
    326  1.1  christos 			       const IDESC *idesc ATTRIBUTE_UNUSED,
    327  1.1  christos 			       int unit_num ATTRIBUTE_UNUSED,
    328  1.1  christos 			       int referenced ATTRIBUTE_UNUSED,
    329  1.1  christos 			       /* Deliberate order.  */
    330  1.1  christos 			       INT addrreg, INT limreg)
    331  1.1  christos {
    332  1.1  christos   USI addr;
    333  1.1  christos   MODEL_CRISV32_DATA *model_data
    334  1.1  christos     = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
    335  1.1  christos 
    336  1.1  christos   if (limreg == -1 || addrreg == -1)
    337  1.1  christos     abort ();
    338  1.1  christos 
    339  1.1  christos   addr = GET_H_GR (addrreg);
    340  1.1  christos 
    341  1.1  christos   /* The movem-to-memory instruction must not move a register modified
    342  1.1  christos      in one of the previous two cycles.  Enforce by adding penalty
    343  1.1  christos      cycles.  */
    344  1.1  christos   if (model_data->prev_modf_regs & ((1 << (limreg + 1)) - 1))
    345  1.1  christos     {
    346  1.1  christos       PENALIZE1 (movemsrc_stall_count);
    347  1.1  christos       PENALIZE1 (movemsrc_stall_count);
    348  1.1  christos     }
    349  1.1  christos   else if (model_data->prev_prev_modf_regs & ((1 << (limreg + 1)) - 1))
    350  1.1  christos     PENALIZE1 (movemsrc_stall_count);
    351  1.1  christos 
    352  1.1  christos   /* One-cycle penalty for each cache-line straddled.  Use the
    353  1.1  christos      documented expressions.  Unfortunately no penalty cycles are
    354  1.1  christos      eliminated by any penalty cycles above.  We file these numbers
    355  1.1  christos      separately, since they aren't schedulable for all cases.  */
    356  1.1  christos   if ((addr >> 5) == (((addr + 4 * (limreg + 1)) - 1) >> 5))
    357  1.1  christos     ;
    358  1.1  christos   else if ((addr >> 5) == (((addr + 4 * (limreg + 1)) - 1) >> 5) - 1)
    359  1.1  christos     PENALIZE1 (movemaddr_stall_count);
    360  1.1  christos   else if ((addr >> 5) == (((addr + 4 * (limreg + 1)) - 1) >> 5) - 2)
    361  1.1  christos     {
    362  1.1  christos       PENALIZE1 (movemaddr_stall_count);
    363  1.1  christos       PENALIZE1 (movemaddr_stall_count);
    364  1.1  christos     }
    365  1.1  christos   else
    366  1.1  christos     abort ();
    367  1.1  christos 
    368  1.1  christos   return 0;
    369  1.1  christos }
    370  1.1  christos 
    371  1.1  christos /* Model function for u-movem-mtor unit.  */
    372  1.1  christos 
    373  1.1  christos int
    374  1.1  christos MY (XCONCAT3 (f_model_crisv,BASENUM,
    375  1.1  christos 	      _u_movem_mtor)) (SIM_CPU *current_cpu,
    376  1.1  christos 			       const IDESC *idesc ATTRIBUTE_UNUSED,
    377  1.1  christos 			       int unit_num ATTRIBUTE_UNUSED,
    378  1.1  christos 			       int referenced ATTRIBUTE_UNUSED,
    379  1.1  christos 			       /* Deliberate order.  */
    380  1.1  christos 			       INT addrreg, INT limreg)
    381  1.1  christos {
    382  1.1  christos   USI addr;
    383  1.1  christos   int nregs = limreg + 1;
    384  1.1  christos   MODEL_CRISV32_DATA *model_data
    385  1.1  christos     = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
    386  1.1  christos 
    387  1.1  christos   if (limreg == -1 || addrreg == -1)
    388  1.1  christos     abort ();
    389  1.1  christos 
    390  1.1  christos   addr = GET_H_GR (addrreg);
    391  1.1  christos 
    392  1.1  christos   /* One-cycle penalty for each cache-line straddled.  Use the
    393  1.1  christos      documented expressions.  One cycle is the norm; more cycles are
    394  1.1  christos      counted as penalties.  Unfortunately no penalty cycles here
    395  1.1  christos      eliminate penalty cycles indicated in ->movem_dest_regs.  */
    396  1.1  christos   if ((addr >> 5) == (((addr + 4 * nregs) - 1) >> 5) - 1)
    397  1.1  christos     PENALIZE1 (movemaddr_stall_count);
    398  1.1  christos   else if ((addr >> 5) == (((addr + 4 * nregs) - 1) >> 5) - 2)
    399  1.1  christos     {
    400  1.1  christos       PENALIZE1 (movemaddr_stall_count);
    401  1.1  christos       PENALIZE1 (movemaddr_stall_count);
    402  1.1  christos     }
    403  1.1  christos 
    404  1.1  christos   model_data->modf_regs |= ((1 << nregs) - 1);
    405  1.1  christos   model_data->movem_dest_regs  |= ((1 << nregs) - 1);
    406  1.1  christos   return 0;
    407  1.1  christos }
    408  1.1  christos 
    409  1.1  christos 
    410  1.1  christos /* Model function for u-branch unit.
    411  1.1  christos    FIXME: newpc and cc are always wrong.  */
    412  1.1  christos 
    413  1.1  christos int
    414  1.1  christos MY (XCONCAT3 (f_model_crisv,BASENUM,_u_branch)) (SIM_CPU *current_cpu,
    415  1.1  christos 						 const IDESC *idesc,
    416  1.1  christos 						 int unit_num, int referenced)
    417  1.1  christos {
    418  1.1  christos   CRIS_MISC_PROFILE *profp = CPU_CRIS_MISC_PROFILE (current_cpu);
    419  1.1  christos   USI pc = profp->old_pc;
    420  1.1  christos   MODEL_CRISV32_DATA *model_data
    421  1.1  christos     = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
    422  1.1  christos   int taken = profp->branch_taken;
    423  1.1  christos   int branch_index = (pc & (N_CRISV32_BRANCH_PREDICTORS - 1)) >> 1;
    424  1.1  christos   int pred_taken = (profp->branch_predictors[branch_index] & 2) != 0;
    425  1.1  christos 
    426  1.1  christos   if (taken != pred_taken)
    427  1.1  christos     {
    428  1.1  christos       PENALIZE1 (branch_stall_count);
    429  1.1  christos       PENALIZE1 (branch_stall_count);
    430  1.1  christos     }
    431  1.1  christos 
    432  1.1  christos   if (taken)
    433  1.1  christos     {
    434  1.1  christos       if (profp->branch_predictors[branch_index] < 3)
    435  1.1  christos 	profp->branch_predictors[branch_index]++;
    436  1.1  christos 
    437  1.1  christos       return MY (XCONCAT3 (f_model_crisv,BASENUM,_u_jump))
    438  1.1  christos 	(current_cpu, idesc, unit_num, referenced, -1);
    439  1.1  christos     }
    440  1.1  christos 
    441  1.1  christos   if (profp->branch_predictors[branch_index] != 0)
    442  1.1  christos     profp->branch_predictors[branch_index]--;
    443  1.1  christos 
    444  1.1  christos   return 0;
    445  1.1  christos }
    446  1.1  christos 
    447  1.1  christos /* Model function for u-jump-r unit.  */
    448  1.1  christos 
    449  1.1  christos int
    450  1.1  christos MY (XCONCAT3 (f_model_crisv,BASENUM,
    451  1.1  christos 	      _u_jump_r)) (SIM_CPU *current_cpu,
    452  1.1  christos 			   const IDESC *idesc ATTRIBUTE_UNUSED,
    453  1.1  christos 			   int unit_num ATTRIBUTE_UNUSED,
    454  1.1  christos 			   int referenced ATTRIBUTE_UNUSED,
    455  1.1  christos 			   int regno)
    456  1.1  christos {
    457  1.1  christos   MODEL_CRISV32_DATA *model_data
    458  1.1  christos     = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
    459  1.1  christos 
    460  1.1  christos   if (regno == -1)
    461  1.1  christos     abort ();
    462  1.1  christos 
    463  1.1  christos   /* For jump-to-register, the register must not have been modified the
    464  1.1  christos      last two cycles.  Penalty: two cycles from the modifying insn.  */
    465  1.1  christos   if ((1 << regno) & model_data->prev_modf_regs)
    466  1.1  christos     {
    467  1.1  christos       PENALIZE1 (jumpsrc_stall_count);
    468  1.1  christos       PENALIZE1 (jumpsrc_stall_count);
    469  1.1  christos     }
    470  1.1  christos   else if ((1 << regno) & model_data->prev_prev_modf_regs)
    471  1.1  christos     PENALIZE1 (jumpsrc_stall_count);
    472  1.1  christos 
    473  1.1  christos   return 0;
    474  1.1  christos }
    475  1.1  christos 
    476  1.1  christos /* Model function for u-jump-sr unit.  */
    477  1.1  christos 
    478  1.1  christos int
    479  1.1  christos MY (XCONCAT3 (f_model_crisv,BASENUM,_u_jump_sr)) (SIM_CPU *current_cpu,
    480  1.1  christos 						  const IDESC *idesc,
    481  1.1  christos 						  int unit_num, int referenced,
    482  1.1  christos 						  int sr_regno)
    483  1.1  christos {
    484  1.1  christos   int regno;
    485  1.1  christos 
    486  1.1  christos   MODEL_CRISV32_DATA *model_data
    487  1.1  christos     = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
    488  1.1  christos 
    489  1.1  christos   if (sr_regno == -1)
    490  1.1  christos     abort ();
    491  1.1  christos 
    492  1.1  christos   regno = sr_regno + 16;
    493  1.1  christos 
    494  1.1  christos   /* For jump-to-register, the register must not have been modified the
    495  1.1  christos      last two cycles.  Penalty: two cycles from the modifying insn.  */
    496  1.1  christos   if ((1 << regno) & model_data->prev_modf_regs)
    497  1.1  christos     {
    498  1.1  christos       PENALIZE1 (jumpsrc_stall_count);
    499  1.1  christos       PENALIZE1 (jumpsrc_stall_count);
    500  1.1  christos     }
    501  1.1  christos   else if ((1 << regno) & model_data->prev_prev_modf_regs)
    502  1.1  christos     PENALIZE1 (jumpsrc_stall_count);
    503  1.1  christos 
    504  1.1  christos   return
    505  1.1  christos     MY (XCONCAT3 (f_model_crisv,BASENUM,_u_jump)) (current_cpu, idesc,
    506  1.1  christos 						   unit_num, referenced, -1);
    507  1.1  christos }
    508  1.1  christos 
    509  1.1  christos /* Model function for u-jump unit.  */
    510  1.1  christos 
    511  1.1  christos int
    512  1.1  christos MY (XCONCAT3 (f_model_crisv,BASENUM,
    513  1.1  christos 	      _u_jump)) (SIM_CPU *current_cpu,
    514  1.1  christos 			 const IDESC *idesc ATTRIBUTE_UNUSED,
    515  1.1  christos 			 int unit_num ATTRIBUTE_UNUSED,
    516  1.1  christos 			 int referenced ATTRIBUTE_UNUSED,
    517  1.1  christos 			 int out_sr_regno)
    518  1.1  christos {
    519  1.1  christos   MODEL_CRISV32_DATA *model_data
    520  1.1  christos     = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
    521  1.1  christos 
    522  1.1  christos   /* Mark that we made a jump.  */
    523  1.1  christos   model_data->modf_regs
    524  1.1  christos     |= (CRIS_MODF_JUMP_MASK
    525  1.1  christos 	| (out_sr_regno == -1 || out_sr_regno == CRIS_BZ_REGNO
    526  1.1  christos 	   ? 0 : (1 << (out_sr_regno + 16))));
    527  1.1  christos   return 0;
    528  1.1  christos }
    529  1.1  christos 
    530  1.1  christos /* Model function for u-multiply unit.  */
    531  1.1  christos 
    532  1.1  christos int
    533  1.1  christos MY (XCONCAT3 (f_model_crisv,BASENUM,
    534  1.1  christos 	      _u_multiply)) (SIM_CPU *current_cpu,
    535  1.1  christos 			     const IDESC *idesc ATTRIBUTE_UNUSED,
    536  1.1  christos 			     int unit_num ATTRIBUTE_UNUSED,
    537  1.1  christos 			     int referenced ATTRIBUTE_UNUSED,
    538  1.1  christos 			     int srcreg, int destreg)
    539  1.1  christos {
    540  1.1  christos   MODEL_CRISV32_DATA *model_data
    541  1.1  christos     = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
    542  1.1  christos 
    543  1.1  christos   /* Sanity-check for cases that should never happen.  */
    544  1.1  christos   if (srcreg == -1 || destreg == -1)
    545  1.1  christos     abort ();
    546  1.1  christos 
    547  1.1  christos   /* This takes extra cycles when one of the inputs has been modified
    548  1.1  christos      through other than autoincrement in the previous cycle.  Penalty:
    549  1.1  christos      one cycle.  */
    550  1.1  christos   if (((1 << srcreg) | (1 << destreg)) & model_data->prev_modf_regs)
    551  1.1  christos     PENALIZE1 (mulsrc_stall_count);
    552  1.1  christos 
    553  1.1  christos   /* We modified the multiplication destination (marked in u-exec) and
    554  1.1  christos      the MOF register.  */
    555  1.1  christos   model_data->modf_regs |= (1 << CRIS_MOF_REGNO);
    556  1.1  christos   return 0;
    557  1.1  christos }
    558  1.1  christos 
    559  1.1  christos #endif /* WITH_PROFILE_MODEL_P */
    560  1.1  christos 
    561  1.1  christos int
    562  1.1  christos MY (deliver_interrupt) (SIM_CPU *current_cpu,
    563  1.1  christos 			enum cris_interrupt_type type,
    564  1.1  christos 			unsigned int vec)
    565  1.1  christos {
    566  1.1  christos   unsigned32 old_ccs, shifted_ccs, new_ccs;
    567  1.1  christos   unsigned char entryaddr_le[4];
    568  1.1  christos   int was_user;
    569  1.1  christos   SIM_DESC sd = CPU_STATE (current_cpu);
    570  1.1  christos   unsigned32 entryaddr;
    571  1.1  christos 
    572  1.1  christos   /* We haven't implemented other interrupt-types yet.  */
    573  1.1  christos   if (type != CRIS_INT_INT)
    574  1.1  christos     abort ();
    575  1.1  christos 
    576  1.1  christos   /* We're called outside of branch delay slots etc, so we don't check
    577  1.1  christos      for that.  */
    578  1.1  christos   if (!GET_H_IBIT_V32 ())
    579  1.1  christos     return 0;
    580  1.1  christos 
    581  1.1  christos   old_ccs = GET_H_SR_V32 (H_SR_CCS);
    582  1.1  christos   shifted_ccs = (old_ccs << 10) & ((1 << 30) - 1);
    583  1.1  christos 
    584  1.1  christos   /* The M bit is handled by code below and the M bit setter function, but
    585  1.1  christos      we need to preserve the Q bit.  */
    586  1.1  christos   new_ccs = shifted_ccs | (old_ccs & (unsigned32) 0x80000000UL);
    587  1.1  christos   was_user = GET_H_UBIT_V32 ();
    588  1.1  christos 
    589  1.1  christos   /* We need to force kernel mode since the setter method doesn't allow
    590  1.1  christos      it.  Then we can use setter methods at will, since they then
    591  1.1  christos      recognize that we're in kernel mode.  */
    592  1.1  christos   CPU (h_ubit_v32) = 0;
    593  1.1  christos 
    594  1.1  christos   SET_H_SR (H_SR_CCS, new_ccs);
    595  1.1  christos 
    596  1.1  christos   if (was_user)
    597  1.1  christos     {
    598  1.1  christos       /* These methods require that user mode is unset.  */
    599  1.1  christos       SET_H_SR (H_SR_USP, GET_H_GR (H_GR_SP));
    600  1.1  christos       SET_H_GR (H_GR_SP, GET_H_KERNEL_SP ());
    601  1.1  christos     }
    602  1.1  christos 
    603  1.1  christos   /* ERP setting is simplified by not taking interrupts in delay-slots
    604  1.1  christos      or when halting.  */
    605  1.1  christos   /* For all other exceptions than guru and NMI, store the return
    606  1.1  christos      address in ERP and set EXS and EXD here.  */
    607  1.1  christos   SET_H_SR (H_SR_ERP, GET_H_PC ());
    608  1.1  christos 
    609  1.1  christos   /* Simplified by not having exception types (fault indications).  */
    610  1.1  christos   SET_H_SR_V32 (H_SR_EXS, (vec * 256));
    611  1.1  christos   SET_H_SR_V32 (H_SR_EDA, 0);
    612  1.1  christos 
    613  1.1  christos   if (sim_core_read_buffer (sd,
    614  1.1  christos 			    current_cpu,
    615  1.1  christos 			    read_map, entryaddr_le,
    616  1.1  christos 			    GET_H_SR (H_SR_EBP) + vec * 4, 4) == 0)
    617  1.1  christos     {
    618  1.1  christos       /* Nothing to do actually; either abort or send a signal.  */
    619  1.1  christos       sim_core_signal (sd, current_cpu, CIA_GET (current_cpu), 0, 4,
    620  1.1  christos 		       GET_H_SR (H_SR_EBP) + vec * 4,
    621  1.1  christos 		       read_transfer, sim_core_unmapped_signal);
    622  1.1  christos       return 0;
    623  1.1  christos     }
    624  1.1  christos 
    625  1.1  christos   entryaddr = bfd_getl32 (entryaddr_le);
    626  1.1  christos   SET_H_PC (entryaddr);
    627  1.1  christos 
    628  1.1  christos   return 1;
    629  1.1  christos }
    630