OSDN Git Service

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