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