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