OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [sim/] [cris/] [crisv32f.c] - Blame information for rev 855

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 227 jeremybenn
/* 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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.