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