Update copyright notices to add year 2010.
[external/binutils.git] / sim / cris / crisv32f.c
1 /* CRIS v32 simulator support code
2    Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
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 }