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