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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [sim/] [cris/] [crisv32f.c] - Blame information for rev 438

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

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

powered by: WebSVN 2.1.0

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