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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gdb/] [gdb-6.8/] [sim/] [frv/] [frv.c] - Blame information for rev 26

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 26 jlechner
/* frv simulator support code
2
   Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2007, 2008
3
   Free Software Foundation, Inc.
4
   Contributed by Red Hat.
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
#define WANT_CPU
22
#define WANT_CPU_FRVBF
23
 
24
#include "sim-main.h"
25
#include "cgen-mem.h"
26
#include "cgen-ops.h"
27
#include "cgen-engine.h"
28
#include "cgen-par.h"
29
#include "bfd.h"
30
#include "gdb/sim-frv.h"
31
#include <math.h>
32
 
33
/* Maintain a flag in order to know when to write the address of the next
34
   VLIW instruction into the LR register.  Used by JMPL. JMPIL, and CALL
35
   insns.  */
36
int frvbf_write_next_vliw_addr_to_LR;
37
 
38
/* The contents of BUF are in target byte order.  */
39
int
40
frvbf_fetch_register (SIM_CPU *current_cpu, int rn, unsigned char *buf, int len)
41
{
42
  if (SIM_FRV_GR0_REGNUM <= rn && rn <= SIM_FRV_GR63_REGNUM)
43
    {
44
      int hi_available, lo_available;
45
      int grn = rn - SIM_FRV_GR0_REGNUM;
46
 
47
      frv_gr_registers_available (current_cpu, &hi_available, &lo_available);
48
 
49
      if ((grn < 32 && !lo_available) || (grn >= 32 && !hi_available))
50
        return 0;
51
      else
52
        SETTSI (buf, GET_H_GR (grn));
53
    }
54
  else if (SIM_FRV_FR0_REGNUM <= rn && rn <= SIM_FRV_FR63_REGNUM)
55
    {
56
      int hi_available, lo_available;
57
      int frn = rn - SIM_FRV_FR0_REGNUM;
58
 
59
      frv_fr_registers_available (current_cpu, &hi_available, &lo_available);
60
 
61
      if ((frn < 32 && !lo_available) || (frn >= 32 && !hi_available))
62
        return 0;
63
      else
64
        SETTSI (buf, GET_H_FR (frn));
65
    }
66
  else if (rn == SIM_FRV_PC_REGNUM)
67
    SETTSI (buf, GET_H_PC ());
68
  else if (SIM_FRV_SPR0_REGNUM <= rn && rn <= SIM_FRV_SPR4095_REGNUM)
69
    {
70
      /* Make sure the register is implemented.  */
71
      FRV_REGISTER_CONTROL *control = CPU_REGISTER_CONTROL (current_cpu);
72
      int spr = rn - SIM_FRV_SPR0_REGNUM;
73
      if (! control->spr[spr].implemented)
74
        return 0;
75
      SETTSI (buf, GET_H_SPR (spr));
76
    }
77
  else
78
    {
79
      SETTSI (buf, 0xdeadbeef);
80
      return 0;
81
    }
82
 
83
  return len;
84
}
85
 
86
/* The contents of BUF are in target byte order.  */
87
 
88
int
89
frvbf_store_register (SIM_CPU *current_cpu, int rn, unsigned char *buf, int len)
90
{
91
  if (SIM_FRV_GR0_REGNUM <= rn && rn <= SIM_FRV_GR63_REGNUM)
92
    {
93
      int hi_available, lo_available;
94
      int grn = rn - SIM_FRV_GR0_REGNUM;
95
 
96
      frv_gr_registers_available (current_cpu, &hi_available, &lo_available);
97
 
98
      if ((grn < 32 && !lo_available) || (grn >= 32 && !hi_available))
99
        return 0;
100
      else
101
        SET_H_GR (grn, GETTSI (buf));
102
    }
103
  else if (SIM_FRV_FR0_REGNUM <= rn && rn <= SIM_FRV_FR63_REGNUM)
104
    {
105
      int hi_available, lo_available;
106
      int frn = rn - SIM_FRV_FR0_REGNUM;
107
 
108
      frv_fr_registers_available (current_cpu, &hi_available, &lo_available);
109
 
110
      if ((frn < 32 && !lo_available) || (frn >= 32 && !hi_available))
111
        return 0;
112
      else
113
        SET_H_FR (frn, GETTSI (buf));
114
    }
115
  else if (rn == SIM_FRV_PC_REGNUM)
116
    SET_H_PC (GETTSI (buf));
117
  else if (SIM_FRV_SPR0_REGNUM <= rn && rn <= SIM_FRV_SPR4095_REGNUM)
118
    {
119
      /* Make sure the register is implemented.  */
120
      FRV_REGISTER_CONTROL *control = CPU_REGISTER_CONTROL (current_cpu);
121
      int spr = rn - SIM_FRV_SPR0_REGNUM;
122
      if (! control->spr[spr].implemented)
123
        return 0;
124
      SET_H_SPR (spr, GETTSI (buf));
125
    }
126
  else
127
    return 0;
128
 
129
  return len;
130
}
131
 
132
/* Cover fns to access the general registers.  */
133
USI
134
frvbf_h_gr_get_handler (SIM_CPU *current_cpu, UINT gr)
135
{
136
  frv_check_gr_access (current_cpu, gr);
137
  return CPU (h_gr[gr]);
138
}
139
 
140
void
141
frvbf_h_gr_set_handler (SIM_CPU *current_cpu, UINT gr, USI newval)
142
{
143
  frv_check_gr_access (current_cpu, gr);
144
 
145
  if (gr == 0)
146
    return; /* Storing into gr0 has no effect.  */
147
 
148
  CPU (h_gr[gr]) = newval;
149
}
150
 
151
/* Cover fns to access the floating point registers.  */
152
SF
153
frvbf_h_fr_get_handler (SIM_CPU *current_cpu, UINT fr)
154
{
155
  frv_check_fr_access (current_cpu, fr);
156
  return CPU (h_fr[fr]);
157
}
158
 
159
void
160
frvbf_h_fr_set_handler (SIM_CPU *current_cpu, UINT fr, SF newval)
161
{
162
  frv_check_fr_access (current_cpu, fr);
163
  CPU (h_fr[fr]) = newval;
164
}
165
 
166
/* Cover fns to access the general registers as double words.  */
167
static UINT
168
check_register_alignment (SIM_CPU *current_cpu, UINT reg, int align_mask)
169
{
170
  if (reg & align_mask)
171
    {
172
      SIM_DESC sd = CPU_STATE (current_cpu);
173
      switch (STATE_ARCHITECTURE (sd)->mach)
174
        {
175
          /* Note: there is a discrepancy between V2.2 of the FR400
176
             instruction manual and the various FR4xx LSI specs.
177
             The former claims that unaligned registers cause a
178
             register_exception while the latter say it's an
179
             illegal_instruction.  The LSI specs appear to be
180
             correct; in fact, the FR4xx series is not documented
181
             as having a register_exception.  */
182
        case bfd_mach_fr400:
183
        case bfd_mach_fr450:
184
        case bfd_mach_fr550:
185
          frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
186
          break;
187
        case bfd_mach_frvtomcat:
188
        case bfd_mach_fr500:
189
        case bfd_mach_frv:
190
          frv_queue_register_exception_interrupt (current_cpu,
191
                                                  FRV_REC_UNALIGNED);
192
          break;
193
        default:
194
          break;
195
        }
196
 
197
      reg &= ~align_mask;
198
    }
199
 
200
  return reg;
201
}
202
 
203
static UINT
204
check_fr_register_alignment (SIM_CPU *current_cpu, UINT reg, int align_mask)
205
{
206
  if (reg & align_mask)
207
    {
208
      SIM_DESC sd = CPU_STATE (current_cpu);
209
      switch (STATE_ARCHITECTURE (sd)->mach)
210
        {
211
          /* See comment in check_register_alignment().  */
212
        case bfd_mach_fr400:
213
        case bfd_mach_fr450:
214
        case bfd_mach_fr550:
215
          frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
216
          break;
217
        case bfd_mach_frvtomcat:
218
        case bfd_mach_fr500:
219
        case bfd_mach_frv:
220
          {
221
            struct frv_fp_exception_info fp_info = {
222
              FSR_NO_EXCEPTION, FTT_INVALID_FR
223
            };
224
            frv_queue_fp_exception_interrupt (current_cpu, & fp_info);
225
          }
226
          break;
227
        default:
228
          break;
229
        }
230
 
231
      reg &= ~align_mask;
232
    }
233
 
234
  return reg;
235
}
236
 
237
static UINT
238
check_memory_alignment (SIM_CPU *current_cpu, SI address, int align_mask)
239
{
240
  if (address & align_mask)
241
    {
242
      SIM_DESC sd = CPU_STATE (current_cpu);
243
      switch (STATE_ARCHITECTURE (sd)->mach)
244
        {
245
          /* See comment in check_register_alignment().  */
246
        case bfd_mach_fr400:
247
        case bfd_mach_fr450:
248
          frv_queue_data_access_error_interrupt (current_cpu, address);
249
          break;
250
        case bfd_mach_frvtomcat:
251
        case bfd_mach_fr500:
252
        case bfd_mach_frv:
253
          frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
254
          break;
255
        default:
256
          break;
257
        }
258
 
259
      address &= ~align_mask;
260
    }
261
 
262
  return address;
263
}
264
 
265
DI
266
frvbf_h_gr_double_get_handler (SIM_CPU *current_cpu, UINT gr)
267
{
268
  DI value;
269
 
270
  if (gr == 0)
271
    return 0; /* gr0 is always 0.  */
272
 
273
  /* Check the register alignment.  */
274
  gr = check_register_alignment (current_cpu, gr, 1);
275
 
276
  value = GET_H_GR (gr);
277
  value <<= 32;
278
  value |=  (USI) GET_H_GR (gr + 1);
279
  return value;
280
}
281
 
282
void
283
frvbf_h_gr_double_set_handler (SIM_CPU *current_cpu, UINT gr, DI newval)
284
{
285
  if (gr == 0)
286
    return; /* Storing into gr0 has no effect.  */
287
 
288
  /* Check the register alignment.  */
289
  gr = check_register_alignment (current_cpu, gr, 1);
290
 
291
  SET_H_GR (gr    , (newval >> 32) & 0xffffffff);
292
  SET_H_GR (gr + 1, (newval      ) & 0xffffffff);
293
}
294
 
295
/* Cover fns to access the floating point register as double words.  */
296
DF
297
frvbf_h_fr_double_get_handler (SIM_CPU *current_cpu, UINT fr)
298
{
299
  union {
300
    SF as_sf[2];
301
    DF as_df;
302
  } value;
303
 
304
  /* Check the register alignment.  */
305
  fr = check_fr_register_alignment (current_cpu, fr, 1);
306
 
307
  if (CURRENT_HOST_BYTE_ORDER == LITTLE_ENDIAN)
308
    {
309
      value.as_sf[1] = GET_H_FR (fr);
310
      value.as_sf[0] = GET_H_FR (fr + 1);
311
    }
312
  else
313
    {
314
      value.as_sf[0] = GET_H_FR (fr);
315
      value.as_sf[1] = GET_H_FR (fr + 1);
316
    }
317
 
318
  return value.as_df;
319
}
320
 
321
void
322
frvbf_h_fr_double_set_handler (SIM_CPU *current_cpu, UINT fr, DF newval)
323
{
324
  union {
325
    SF as_sf[2];
326
    DF as_df;
327
  } value;
328
 
329
  /* Check the register alignment.  */
330
  fr = check_fr_register_alignment (current_cpu, fr, 1);
331
 
332
  value.as_df = newval;
333
  if (CURRENT_HOST_BYTE_ORDER == LITTLE_ENDIAN)
334
    {
335
      SET_H_FR (fr    , value.as_sf[1]);
336
      SET_H_FR (fr + 1, value.as_sf[0]);
337
    }
338
  else
339
    {
340
      SET_H_FR (fr    , value.as_sf[0]);
341
      SET_H_FR (fr + 1, value.as_sf[1]);
342
    }
343
}
344
 
345
/* Cover fns to access the floating point register as integer words.  */
346
USI
347
frvbf_h_fr_int_get_handler (SIM_CPU *current_cpu, UINT fr)
348
{
349
  union {
350
    SF  as_sf;
351
    USI as_usi;
352
  } value;
353
 
354
  value.as_sf = GET_H_FR (fr);
355
  return value.as_usi;
356
}
357
 
358
void
359
frvbf_h_fr_int_set_handler (SIM_CPU *current_cpu, UINT fr, USI newval)
360
{
361
  union {
362
    SF  as_sf;
363
    USI as_usi;
364
  } value;
365
 
366
  value.as_usi = newval;
367
  SET_H_FR (fr, value.as_sf);
368
}
369
 
370
/* Cover fns to access the coprocessor registers as double words.  */
371
DI
372
frvbf_h_cpr_double_get_handler (SIM_CPU *current_cpu, UINT cpr)
373
{
374
  DI value;
375
 
376
  /* Check the register alignment.  */
377
  cpr = check_register_alignment (current_cpu, cpr, 1);
378
 
379
  value = GET_H_CPR (cpr);
380
  value <<= 32;
381
  value |=  (USI) GET_H_CPR (cpr + 1);
382
  return value;
383
}
384
 
385
void
386
frvbf_h_cpr_double_set_handler (SIM_CPU *current_cpu, UINT cpr, DI newval)
387
{
388
  /* Check the register alignment.  */
389
  cpr = check_register_alignment (current_cpu, cpr, 1);
390
 
391
  SET_H_CPR (cpr    , (newval >> 32) & 0xffffffff);
392
  SET_H_CPR (cpr + 1, (newval      ) & 0xffffffff);
393
}
394
 
395
/* Cover fns to write registers as quad words.  */
396
void
397
frvbf_h_gr_quad_set_handler (SIM_CPU *current_cpu, UINT gr, SI *newval)
398
{
399
  if (gr == 0)
400
    return; /* Storing into gr0 has no effect.  */
401
 
402
  /* Check the register alignment.  */
403
  gr = check_register_alignment (current_cpu, gr, 3);
404
 
405
  SET_H_GR (gr    , newval[0]);
406
  SET_H_GR (gr + 1, newval[1]);
407
  SET_H_GR (gr + 2, newval[2]);
408
  SET_H_GR (gr + 3, newval[3]);
409
}
410
 
411
void
412
frvbf_h_fr_quad_set_handler (SIM_CPU *current_cpu, UINT fr, SI *newval)
413
{
414
  /* Check the register alignment.  */
415
  fr = check_fr_register_alignment (current_cpu, fr, 3);
416
 
417
  SET_H_FR (fr    , newval[0]);
418
  SET_H_FR (fr + 1, newval[1]);
419
  SET_H_FR (fr + 2, newval[2]);
420
  SET_H_FR (fr + 3, newval[3]);
421
}
422
 
423
void
424
frvbf_h_cpr_quad_set_handler (SIM_CPU *current_cpu, UINT cpr, SI *newval)
425
{
426
  /* Check the register alignment.  */
427
  cpr = check_register_alignment (current_cpu, cpr, 3);
428
 
429
  SET_H_CPR (cpr    , newval[0]);
430
  SET_H_CPR (cpr + 1, newval[1]);
431
  SET_H_CPR (cpr + 2, newval[2]);
432
  SET_H_CPR (cpr + 3, newval[3]);
433
}
434
 
435
/* Cover fns to access the special purpose registers.  */
436
USI
437
frvbf_h_spr_get_handler (SIM_CPU *current_cpu, UINT spr)
438
{
439
  /* Check access restrictions.  */
440
  frv_check_spr_read_access (current_cpu, spr);
441
 
442
  switch (spr)
443
    {
444
    case H_SPR_PSR:
445
      return spr_psr_get_handler (current_cpu);
446
    case H_SPR_TBR:
447
      return spr_tbr_get_handler (current_cpu);
448
    case H_SPR_BPSR:
449
      return spr_bpsr_get_handler (current_cpu);
450
    case H_SPR_CCR:
451
      return spr_ccr_get_handler (current_cpu);
452
    case H_SPR_CCCR:
453
      return spr_cccr_get_handler (current_cpu);
454
    case H_SPR_SR0:
455
    case H_SPR_SR1:
456
    case H_SPR_SR2:
457
    case H_SPR_SR3:
458
      return spr_sr_get_handler (current_cpu, spr);
459
      break;
460
    default:
461
      return CPU (h_spr[spr]);
462
    }
463
  return 0;
464
}
465
 
466
void
467
frvbf_h_spr_set_handler (SIM_CPU *current_cpu, UINT spr, USI newval)
468
{
469
  FRV_REGISTER_CONTROL *control;
470
  USI mask;
471
  USI oldval;
472
 
473
  /* Check access restrictions.  */
474
  frv_check_spr_write_access (current_cpu, spr);
475
 
476
  /* Only set those fields which are writeable.  */
477
  control = CPU_REGISTER_CONTROL (current_cpu);
478
  mask = control->spr[spr].read_only_mask;
479
  oldval = GET_H_SPR (spr);
480
 
481
  newval = (newval & ~mask) | (oldval & mask);
482
 
483
  /* Some registers are represented by individual components which are
484
     referenced more often than the register itself.  */
485
  switch (spr)
486
    {
487
    case H_SPR_PSR:
488
      spr_psr_set_handler (current_cpu, newval);
489
      break;
490
    case H_SPR_TBR:
491
      spr_tbr_set_handler (current_cpu, newval);
492
      break;
493
    case H_SPR_BPSR:
494
      spr_bpsr_set_handler (current_cpu, newval);
495
      break;
496
    case H_SPR_CCR:
497
      spr_ccr_set_handler (current_cpu, newval);
498
      break;
499
    case H_SPR_CCCR:
500
      spr_cccr_set_handler (current_cpu, newval);
501
      break;
502
    case H_SPR_SR0:
503
    case H_SPR_SR1:
504
    case H_SPR_SR2:
505
    case H_SPR_SR3:
506
      spr_sr_set_handler (current_cpu, spr, newval);
507
      break;
508
    case H_SPR_IHSR8:
509
      frv_cache_reconfigure (current_cpu, CPU_INSN_CACHE (current_cpu));
510
      break;
511
    default:
512
      CPU (h_spr[spr]) = newval;
513
      break;
514
    }
515
}
516
 
517
/* Cover fns to access the gr_hi and gr_lo registers.  */
518
UHI
519
frvbf_h_gr_hi_get_handler (SIM_CPU *current_cpu, UINT gr)
520
{
521
  return (GET_H_GR(gr) >> 16) & 0xffff;
522
}
523
 
524
void
525
frvbf_h_gr_hi_set_handler (SIM_CPU *current_cpu, UINT gr, UHI newval)
526
{
527
  USI value = (GET_H_GR (gr) & 0xffff) | (newval << 16);
528
  SET_H_GR (gr, value);
529
}
530
 
531
UHI
532
frvbf_h_gr_lo_get_handler (SIM_CPU *current_cpu, UINT gr)
533
{
534
  return GET_H_GR(gr) & 0xffff;
535
}
536
 
537
void
538
frvbf_h_gr_lo_set_handler (SIM_CPU *current_cpu, UINT gr, UHI newval)
539
{
540
  USI value = (GET_H_GR (gr) & 0xffff0000) | (newval & 0xffff);
541
  SET_H_GR (gr, value);
542
}
543
 
544
/* Cover fns to access the tbr bits.  */
545
USI
546
spr_tbr_get_handler (SIM_CPU *current_cpu)
547
{
548
  int tbr = ((GET_H_TBR_TBA () & 0xfffff) << 12) |
549
            ((GET_H_TBR_TT  () &  0xff) <<  4);
550
 
551
  return tbr;
552
}
553
 
554
void
555
spr_tbr_set_handler (SIM_CPU *current_cpu, USI newval)
556
{
557
  int tbr = newval;
558
 
559
  SET_H_TBR_TBA ((tbr >> 12) & 0xfffff) ;
560
  SET_H_TBR_TT  ((tbr >>  4) & 0xff) ;
561
}
562
 
563
/* Cover fns to access the bpsr bits.  */
564
USI
565
spr_bpsr_get_handler (SIM_CPU *current_cpu)
566
{
567
  int bpsr = ((GET_H_BPSR_BS  () & 0x1) << 12) |
568
             ((GET_H_BPSR_BET () & 0x1)      );
569
 
570
  return bpsr;
571
}
572
 
573
void
574
spr_bpsr_set_handler (SIM_CPU *current_cpu, USI newval)
575
{
576
  int bpsr = newval;
577
 
578
  SET_H_BPSR_BS  ((bpsr >> 12) & 1);
579
  SET_H_BPSR_BET ((bpsr      ) & 1);
580
}
581
 
582
/* Cover fns to access the psr bits.  */
583
USI
584
spr_psr_get_handler (SIM_CPU *current_cpu)
585
{
586
  int psr = ((GET_H_PSR_IMPLE () & 0xf) << 28) |
587
            ((GET_H_PSR_VER   () & 0xf) << 24) |
588
            ((GET_H_PSR_ICE   () & 0x1) << 16) |
589
            ((GET_H_PSR_NEM   () & 0x1) << 14) |
590
            ((GET_H_PSR_CM    () & 0x1) << 13) |
591
            ((GET_H_PSR_BE    () & 0x1) << 12) |
592
            ((GET_H_PSR_ESR   () & 0x1) << 11) |
593
            ((GET_H_PSR_EF    () & 0x1) <<  8) |
594
            ((GET_H_PSR_EM    () & 0x1) <<  7) |
595
            ((GET_H_PSR_PIL   () & 0xf) <<  3) |
596
            ((GET_H_PSR_S     () & 0x1) <<  2) |
597
            ((GET_H_PSR_PS    () & 0x1) <<  1) |
598
            ((GET_H_PSR_ET    () & 0x1)      );
599
 
600
  return psr;
601
}
602
 
603
void
604
spr_psr_set_handler (SIM_CPU *current_cpu, USI newval)
605
{
606
  /* The handler for PSR.S references the value of PSR.ESR, so set PSR.S
607
     first.  */
608
  SET_H_PSR_S ((newval >>  2) & 1);
609
 
610
  SET_H_PSR_IMPLE ((newval >> 28) & 0xf);
611
  SET_H_PSR_VER   ((newval >> 24) & 0xf);
612
  SET_H_PSR_ICE   ((newval >> 16) & 1);
613
  SET_H_PSR_NEM   ((newval >> 14) & 1);
614
  SET_H_PSR_CM    ((newval >> 13) & 1);
615
  SET_H_PSR_BE    ((newval >> 12) & 1);
616
  SET_H_PSR_ESR   ((newval >> 11) & 1);
617
  SET_H_PSR_EF    ((newval >>  8) & 1);
618
  SET_H_PSR_EM    ((newval >>  7) & 1);
619
  SET_H_PSR_PIL   ((newval >>  3) & 0xf);
620
  SET_H_PSR_PS    ((newval >>  1) & 1);
621
  SET_H_PSR_ET    ((newval      ) & 1);
622
}
623
 
624
void
625
frvbf_h_psr_s_set_handler (SIM_CPU *current_cpu, BI newval)
626
{
627
  /* If switching from user to supervisor mode, or vice-versa, then switch
628
     the supervisor/user context.  */
629
  int psr_s = GET_H_PSR_S ();
630
  if (psr_s != (newval & 1))
631
    {
632
      frvbf_switch_supervisor_user_context (current_cpu);
633
      CPU (h_psr_s) = newval & 1;
634
    }
635
}
636
 
637
/* Cover fns to access the ccr bits.  */
638
USI
639
spr_ccr_get_handler (SIM_CPU *current_cpu)
640
{
641
  int ccr = ((GET_H_ICCR (H_ICCR_ICC3) & 0xf) << 28) |
642
            ((GET_H_ICCR (H_ICCR_ICC2) & 0xf) << 24) |
643
            ((GET_H_ICCR (H_ICCR_ICC1) & 0xf) << 20) |
644
            ((GET_H_ICCR (H_ICCR_ICC0) & 0xf) << 16) |
645
            ((GET_H_FCCR (H_FCCR_FCC3) & 0xf) << 12) |
646
            ((GET_H_FCCR (H_FCCR_FCC2) & 0xf) <<  8) |
647
            ((GET_H_FCCR (H_FCCR_FCC1) & 0xf) <<  4) |
648
            ((GET_H_FCCR (H_FCCR_FCC0) & 0xf)      );
649
 
650
  return ccr;
651
}
652
 
653
void
654
spr_ccr_set_handler (SIM_CPU *current_cpu, USI newval)
655
{
656
  int ccr = newval;
657
 
658
  SET_H_ICCR (H_ICCR_ICC3, (newval >> 28) & 0xf);
659
  SET_H_ICCR (H_ICCR_ICC2, (newval >> 24) & 0xf);
660
  SET_H_ICCR (H_ICCR_ICC1, (newval >> 20) & 0xf);
661
  SET_H_ICCR (H_ICCR_ICC0, (newval >> 16) & 0xf);
662
  SET_H_FCCR (H_FCCR_FCC3, (newval >> 12) & 0xf);
663
  SET_H_FCCR (H_FCCR_FCC2, (newval >>  8) & 0xf);
664
  SET_H_FCCR (H_FCCR_FCC1, (newval >>  4) & 0xf);
665
  SET_H_FCCR (H_FCCR_FCC0, (newval      ) & 0xf);
666
}
667
 
668
QI
669
frvbf_set_icc_for_shift_right (
670
  SIM_CPU *current_cpu, SI value, SI shift, QI icc
671
)
672
{
673
  /* Set the C flag of the given icc to the logical OR of the bits shifted
674
     out.  */
675
  int mask = (1 << shift) - 1;
676
  if ((value & mask) != 0)
677
    return icc | 0x1;
678
 
679
  return icc & 0xe;
680
}
681
 
682
QI
683
frvbf_set_icc_for_shift_left (
684
  SIM_CPU *current_cpu, SI value, SI shift, QI icc
685
)
686
{
687
  /* Set the V flag of the given icc to the logical OR of the bits shifted
688
     out.  */
689
  int mask = ((1 << shift) - 1) << (32 - shift);
690
  if ((value & mask) != 0)
691
    return icc | 0x2;
692
 
693
  return icc & 0xd;
694
}
695
 
696
/* Cover fns to access the cccr bits.  */
697
USI
698
spr_cccr_get_handler (SIM_CPU *current_cpu)
699
{
700
  int cccr = ((GET_H_CCCR (H_CCCR_CC7) & 0x3) << 14) |
701
             ((GET_H_CCCR (H_CCCR_CC6) & 0x3) << 12) |
702
             ((GET_H_CCCR (H_CCCR_CC5) & 0x3) << 10) |
703
             ((GET_H_CCCR (H_CCCR_CC4) & 0x3) <<  8) |
704
             ((GET_H_CCCR (H_CCCR_CC3) & 0x3) <<  6) |
705
             ((GET_H_CCCR (H_CCCR_CC2) & 0x3) <<  4) |
706
             ((GET_H_CCCR (H_CCCR_CC1) & 0x3) <<  2) |
707
             ((GET_H_CCCR (H_CCCR_CC0) & 0x3)      );
708
 
709
  return cccr;
710
}
711
 
712
void
713
spr_cccr_set_handler (SIM_CPU *current_cpu, USI newval)
714
{
715
  int cccr = newval;
716
 
717
  SET_H_CCCR (H_CCCR_CC7, (newval >> 14) & 0x3);
718
  SET_H_CCCR (H_CCCR_CC6, (newval >> 12) & 0x3);
719
  SET_H_CCCR (H_CCCR_CC5, (newval >> 10) & 0x3);
720
  SET_H_CCCR (H_CCCR_CC4, (newval >>  8) & 0x3);
721
  SET_H_CCCR (H_CCCR_CC3, (newval >>  6) & 0x3);
722
  SET_H_CCCR (H_CCCR_CC2, (newval >>  4) & 0x3);
723
  SET_H_CCCR (H_CCCR_CC1, (newval >>  2) & 0x3);
724
  SET_H_CCCR (H_CCCR_CC0, (newval      ) & 0x3);
725
}
726
 
727
/* Cover fns to access the sr bits.  */
728
USI
729
spr_sr_get_handler (SIM_CPU *current_cpu, UINT spr)
730
{
731
  /* If PSR.ESR is not set, then SR0-3 map onto SGR4-7 which will be GR4-7,
732
     otherwise the correct mapping of USG4-7 or SGR4-7 will be in SR0-3.  */
733
  int psr_esr = GET_H_PSR_ESR ();
734
  if (! psr_esr)
735
    return GET_H_GR (4 + (spr - H_SPR_SR0));
736
 
737
  return CPU (h_spr[spr]);
738
}
739
 
740
void
741
spr_sr_set_handler (SIM_CPU *current_cpu, UINT spr, USI newval)
742
{
743
  /* If PSR.ESR is not set, then SR0-3 map onto SGR4-7 which will be GR4-7,
744
     otherwise the correct mapping of USG4-7 or SGR4-7 will be in SR0-3.  */
745
  int psr_esr = GET_H_PSR_ESR ();
746
  if (! psr_esr)
747
    SET_H_GR (4 + (spr - H_SPR_SR0), newval);
748
  else
749
    CPU (h_spr[spr]) = newval;
750
}
751
 
752
/* Switch SR0-SR4 with GR4-GR7 if PSR.ESR is set.  */
753
void
754
frvbf_switch_supervisor_user_context (SIM_CPU *current_cpu)
755
{
756
  if (GET_H_PSR_ESR ())
757
    {
758
      /* We need to be in supervisor mode to swap the registers. Access the
759
         PSR.S directly in order to avoid recursive context switches.  */
760
      int i;
761
      int save_psr_s = CPU (h_psr_s);
762
      CPU (h_psr_s) = 1;
763
      for (i = 0; i < 4; ++i)
764
        {
765
          int gr = i + 4;
766
          int spr = i + H_SPR_SR0;
767
          SI tmp = GET_H_SPR (spr);
768
          SET_H_SPR (spr, GET_H_GR (gr));
769
          SET_H_GR (gr, tmp);
770
        }
771
      CPU (h_psr_s) = save_psr_s;
772
    }
773
}
774
 
775
/* Handle load/store of quad registers.  */
776
void
777
frvbf_load_quad_GR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI targ_ix)
778
{
779
  int i;
780
  SI value[4];
781
 
782
  /* Check memory alignment */
783
  address = check_memory_alignment (current_cpu, address, 0xf);
784
 
785
  /* If we need to count cycles, then the cache operation will be
786
     initiated from the model profiling functions.
787
     See frvbf_model_....  */
788
  if (model_insn)
789
    {
790
      CPU_LOAD_ADDRESS (current_cpu) = address;
791
      CPU_LOAD_LENGTH (current_cpu) = 16;
792
    }
793
  else
794
    {
795
      for (i = 0; i < 4; ++i)
796
        {
797
          value[i] = frvbf_read_mem_SI (current_cpu, pc, address);
798
          address += 4;
799
        }
800
      sim_queue_fn_xi_write (current_cpu, frvbf_h_gr_quad_set_handler, targ_ix,
801
                             value);
802
    }
803
}
804
 
805
void
806
frvbf_store_quad_GR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI src_ix)
807
{
808
  int i;
809
  SI value[4];
810
  USI hsr0;
811
 
812
  /* Check register and memory alignment.  */
813
  src_ix = check_register_alignment (current_cpu, src_ix, 3);
814
  address = check_memory_alignment (current_cpu, address, 0xf);
815
 
816
  for (i = 0; i < 4; ++i)
817
    {
818
      /* GR0 is always 0.  */
819
      if (src_ix == 0)
820
        value[i] = 0;
821
      else
822
        value[i] = GET_H_GR (src_ix + i);
823
    }
824
  hsr0 = GET_HSR0 ();
825
  if (GET_HSR0_DCE (hsr0))
826
    sim_queue_fn_mem_xi_write (current_cpu, frvbf_mem_set_XI, address, value);
827
  else
828
    sim_queue_mem_xi_write (current_cpu, address, value);
829
}
830
 
831
void
832
frvbf_load_quad_FRint (SIM_CPU *current_cpu, PCADDR pc, SI address, SI targ_ix)
833
{
834
  int i;
835
  SI value[4];
836
 
837
  /* Check memory alignment */
838
  address = check_memory_alignment (current_cpu, address, 0xf);
839
 
840
  /* If we need to count cycles, then the cache operation will be
841
     initiated from the model profiling functions.
842
     See frvbf_model_....  */
843
  if (model_insn)
844
    {
845
      CPU_LOAD_ADDRESS (current_cpu) = address;
846
      CPU_LOAD_LENGTH (current_cpu) = 16;
847
    }
848
  else
849
    {
850
      for (i = 0; i < 4; ++i)
851
        {
852
          value[i] = frvbf_read_mem_SI (current_cpu, pc, address);
853
          address += 4;
854
        }
855
      sim_queue_fn_xi_write (current_cpu, frvbf_h_fr_quad_set_handler, targ_ix,
856
                             value);
857
    }
858
}
859
 
860
void
861
frvbf_store_quad_FRint (SIM_CPU *current_cpu, PCADDR pc, SI address, SI src_ix)
862
{
863
  int i;
864
  SI value[4];
865
  USI hsr0;
866
 
867
  /* Check register and memory alignment.  */
868
  src_ix = check_fr_register_alignment (current_cpu, src_ix, 3);
869
  address = check_memory_alignment (current_cpu, address, 0xf);
870
 
871
  for (i = 0; i < 4; ++i)
872
    value[i] = GET_H_FR (src_ix + i);
873
 
874
  hsr0 = GET_HSR0 ();
875
  if (GET_HSR0_DCE (hsr0))
876
    sim_queue_fn_mem_xi_write (current_cpu, frvbf_mem_set_XI, address, value);
877
  else
878
    sim_queue_mem_xi_write (current_cpu, address, value);
879
}
880
 
881
void
882
frvbf_load_quad_CPR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI targ_ix)
883
{
884
  int i;
885
  SI value[4];
886
 
887
  /* Check memory alignment */
888
  address = check_memory_alignment (current_cpu, address, 0xf);
889
 
890
  /* If we need to count cycles, then the cache operation will be
891
     initiated from the model profiling functions.
892
     See frvbf_model_....  */
893
  if (model_insn)
894
    {
895
      CPU_LOAD_ADDRESS (current_cpu) = address;
896
      CPU_LOAD_LENGTH (current_cpu) = 16;
897
    }
898
  else
899
    {
900
      for (i = 0; i < 4; ++i)
901
        {
902
          value[i] = frvbf_read_mem_SI (current_cpu, pc, address);
903
          address += 4;
904
        }
905
      sim_queue_fn_xi_write (current_cpu, frvbf_h_cpr_quad_set_handler, targ_ix,
906
                             value);
907
    }
908
}
909
 
910
void
911
frvbf_store_quad_CPR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI src_ix)
912
{
913
  int i;
914
  SI value[4];
915
  USI hsr0;
916
 
917
  /* Check register and memory alignment.  */
918
  src_ix = check_register_alignment (current_cpu, src_ix, 3);
919
  address = check_memory_alignment (current_cpu, address, 0xf);
920
 
921
  for (i = 0; i < 4; ++i)
922
    value[i] = GET_H_CPR (src_ix + i);
923
 
924
  hsr0 = GET_HSR0 ();
925
  if (GET_HSR0_DCE (hsr0))
926
    sim_queue_fn_mem_xi_write (current_cpu, frvbf_mem_set_XI, address, value);
927
  else
928
    sim_queue_mem_xi_write (current_cpu, address, value);
929
}
930
 
931
void
932
frvbf_signed_integer_divide (
933
  SIM_CPU *current_cpu, SI arg1, SI arg2, int target_index, int non_excepting
934
)
935
{
936
  enum frv_dtt dtt = FRV_DTT_NO_EXCEPTION;
937
  if (arg1 == 0x80000000 && arg2 == -1)
938
    {
939
      /* 0x80000000/(-1) must result in 0x7fffffff when ISR.EDE is set
940
         otherwise it may result in 0x7fffffff (sparc compatibility) or
941
         0x80000000 (C language compatibility). */
942
      USI isr;
943
      dtt = FRV_DTT_OVERFLOW;
944
 
945
      isr = GET_ISR ();
946
      if (GET_ISR_EDE (isr))
947
        sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index,
948
                               0x7fffffff);
949
      else
950
        sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index,
951
                               0x80000000);
952
      frvbf_force_update (current_cpu); /* Force update of target register.  */
953
    }
954
  else if (arg2 == 0)
955
    dtt = FRV_DTT_DIVISION_BY_ZERO;
956
  else
957
    sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index,
958
                           arg1 / arg2);
959
 
960
  /* Check for exceptions.  */
961
  if (dtt != FRV_DTT_NO_EXCEPTION)
962
    dtt = frvbf_division_exception (current_cpu, dtt, target_index,
963
                                    non_excepting);
964
  if (non_excepting && dtt == FRV_DTT_NO_EXCEPTION)
965
    {
966
      /* Non excepting instruction. Clear the NE flag for the target
967
         register.  */
968
      SI NE_flags[2];
969
      GET_NE_FLAGS (NE_flags, H_SPR_GNER0);
970
      CLEAR_NE_FLAG (NE_flags, target_index);
971
      SET_NE_FLAGS (H_SPR_GNER0, NE_flags);
972
    }
973
}
974
 
975
void
976
frvbf_unsigned_integer_divide (
977
  SIM_CPU *current_cpu, USI arg1, USI arg2, int target_index, int non_excepting
978
)
979
{
980
  if (arg2 == 0)
981
    frvbf_division_exception (current_cpu, FRV_DTT_DIVISION_BY_ZERO,
982
                              target_index, non_excepting);
983
  else
984
    {
985
      sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index,
986
                             arg1 / arg2);
987
      if (non_excepting)
988
        {
989
          /* Non excepting instruction. Clear the NE flag for the target
990
             register.  */
991
          SI NE_flags[2];
992
          GET_NE_FLAGS (NE_flags, H_SPR_GNER0);
993
          CLEAR_NE_FLAG (NE_flags, target_index);
994
          SET_NE_FLAGS (H_SPR_GNER0, NE_flags);
995
        }
996
    }
997
}
998
 
999
/* Clear accumulators.  */
1000
void
1001
frvbf_clear_accumulators (SIM_CPU *current_cpu, SI acc_ix, int A)
1002
{
1003
  SIM_DESC sd = CPU_STATE (current_cpu);
1004
  int acc_mask =
1005
    (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr500) ? 7 :
1006
    (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) ? 7 :
1007
    (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450) ? 11 :
1008
    (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400) ? 3 :
1009
    63;
1010
  FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu);
1011
 
1012
  ps->mclracc_acc = acc_ix;
1013
  ps->mclracc_A   = A;
1014
  if (A == 0 || acc_ix != 0) /* Clear 1 accumuator?  */
1015
    {
1016
      /* This instruction is a nop if the referenced accumulator is not
1017
         implemented. */
1018
      if ((acc_ix & acc_mask) == acc_ix)
1019
        sim_queue_fn_di_write (current_cpu, frvbf_h_acc40S_set, acc_ix, 0);
1020
    }
1021
  else
1022
    {
1023
      /* Clear all implemented accumulators.  */
1024
      int i;
1025
      for (i = 0; i <= acc_mask; ++i)
1026
        if ((i & acc_mask) == i)
1027
          sim_queue_fn_di_write (current_cpu, frvbf_h_acc40S_set, i, 0);
1028
    }
1029
}
1030
 
1031
/* Functions to aid insn semantics.  */
1032
 
1033
/* Compute the result of the SCAN and SCANI insns after the shift and xor.  */
1034
SI
1035
frvbf_scan_result (SIM_CPU *current_cpu, SI value)
1036
{
1037
  SI i;
1038
  SI mask;
1039
 
1040
  if (value == 0)
1041
    return 63;
1042
 
1043
  /* Find the position of the first non-zero bit.
1044
     The loop will terminate since there is guaranteed to be at least one
1045
     non-zero bit.  */
1046
  mask = 1 << (sizeof (mask) * 8 - 1);
1047
  for (i = 0; (value & mask) == 0; ++i)
1048
    value <<= 1;
1049
 
1050
  return i;
1051
}
1052
 
1053
/* Compute the result of the cut insns.  */
1054
SI
1055
frvbf_cut (SIM_CPU *current_cpu, SI reg1, SI reg2, SI cut_point)
1056
{
1057
  SI result;
1058
  cut_point &= 0x3f;
1059
  if (cut_point < 32)
1060
    {
1061
      result = reg1 << cut_point;
1062
      result |= (reg2 >> (32 - cut_point)) & ((1 << cut_point) - 1);
1063
    }
1064
  else
1065
    result = reg2 << (cut_point - 32);
1066
 
1067
  return result;
1068
}
1069
 
1070
/* Compute the result of the cut insns.  */
1071
SI
1072
frvbf_media_cut (SIM_CPU *current_cpu, DI acc, SI cut_point)
1073
{
1074
  /* The cut point is the lower 6 bits (signed) of what we are passed.  */
1075
  cut_point = cut_point << 26 >> 26;
1076
 
1077
  /* The cut_point is relative to bit 40 of 64 bits.  */
1078
  if (cut_point >= 0)
1079
    return (acc << (cut_point + 24)) >> 32;
1080
 
1081
  /* Extend the sign bit (bit 40) for negative cuts.  */
1082
  if (cut_point == -32)
1083
    return (acc << 24) >> 63; /* Special case for full shiftout.  */
1084
 
1085
  return (acc << 24) >> (32 + -cut_point);
1086
}
1087
 
1088
/* Compute the result of the cut insns.  */
1089
SI
1090
frvbf_media_cut_ss (SIM_CPU *current_cpu, DI acc, SI cut_point)
1091
{
1092
  /* The cut point is the lower 6 bits (signed) of what we are passed.  */
1093
  cut_point = cut_point << 26 >> 26;
1094
 
1095
  if (cut_point >= 0)
1096
    {
1097
      /* The cut_point is relative to bit 40 of 64 bits.  */
1098
      DI shifted = acc << (cut_point + 24);
1099
      DI unshifted = shifted >> (cut_point + 24);
1100
 
1101
      /* The result will be saturated if significant bits are shifted out.  */
1102
      if (unshifted != acc)
1103
        {
1104
          if (acc < 0)
1105
            return 0x80000000;
1106
          return 0x7fffffff;
1107
        }
1108
    }
1109
 
1110
  /* The result will not be saturated, so use the code for the normal cut.  */
1111
  return frvbf_media_cut (current_cpu, acc, cut_point);
1112
}
1113
 
1114
/* Compute the result of int accumulator cut (SCUTSS).  */
1115
SI
1116
frvbf_iacc_cut (SIM_CPU *current_cpu, DI acc, SI cut_point)
1117
{
1118
  DI lower, upper;
1119
 
1120
  /* The cut point is the lower 7 bits (signed) of what we are passed.  */
1121
  cut_point = cut_point << 25 >> 25;
1122
 
1123
  /* Conceptually, the operation is on a 128-bit sign-extension of ACC.
1124
     The top bit of the return value corresponds to bit (63 - CUT_POINT)
1125
     of this 128-bit value.
1126
 
1127
     Since we can't deal with 128-bit values very easily, convert the
1128
     operation into an equivalent 64-bit one.  */
1129
  if (cut_point < 0)
1130
    {
1131
      /* Avoid an undefined shift operation.  */
1132
      if (cut_point == -64)
1133
        acc >>= 63;
1134
      else
1135
        acc >>= -cut_point;
1136
      cut_point = 0;
1137
    }
1138
 
1139
  /* Get the shifted but unsaturated result.  Set LOWER to the lowest
1140
     32 bits of the result and UPPER to the result >> 31.  */
1141
  if (cut_point < 32)
1142
    {
1143
      /* The cut loses the (32 - CUT_POINT) least significant bits.
1144
         Round the result up if the most significant of these lost bits
1145
         is 1.  */
1146
      lower = acc >> (32 - cut_point);
1147
      if (lower < 0x7fffffff)
1148
        if (acc & LSBIT64 (32 - cut_point - 1))
1149
          lower++;
1150
      upper = lower >> 31;
1151
    }
1152
  else
1153
    {
1154
      lower = acc << (cut_point - 32);
1155
      upper = acc >> (63 - cut_point);
1156
    }
1157
 
1158
  /* Saturate the result.  */
1159
  if (upper < -1)
1160
    return ~0x7fffffff;
1161
  else if (upper > 0)
1162
    return 0x7fffffff;
1163
  else
1164
    return lower;
1165
}
1166
 
1167
/* Compute the result of shift-left-arithmetic-with-saturation (SLASS).  */
1168
SI
1169
frvbf_shift_left_arith_saturate (SIM_CPU *current_cpu, SI arg1, SI arg2)
1170
{
1171
  int neg_arg1;
1172
 
1173
  /* FIXME: what to do with negative shift amt?  */
1174
  if (arg2 <= 0)
1175
    return arg1;
1176
 
1177
  if (arg1 == 0)
1178
    return 0;
1179
 
1180
  /* Signed shift by 31 or greater saturates by definition.  */
1181
  if (arg2 >= 31)
1182
    if (arg1 > 0)
1183
      return (SI) 0x7fffffff;
1184
    else
1185
      return (SI) 0x80000000;
1186
 
1187
  /* OK, arg2 is between 1 and 31.  */
1188
  neg_arg1 = (arg1 < 0);
1189
  do {
1190
    arg1 <<= 1;
1191
    /* Check for sign bit change (saturation).  */
1192
    if (neg_arg1 && (arg1 >= 0))
1193
      return (SI) 0x80000000;
1194
    else if (!neg_arg1 && (arg1 < 0))
1195
      return (SI) 0x7fffffff;
1196
  } while (--arg2 > 0);
1197
 
1198
  return arg1;
1199
}
1200
 
1201
/* Simulate the media custom insns.  */
1202
void
1203
frvbf_media_cop (SIM_CPU *current_cpu, int cop_num)
1204
{
1205
  /* The semantics of the insn are a nop, since it is implementation defined.
1206
     We do need to check whether it's implemented and set up for MTRAP
1207
     if it's not.  */
1208
  USI msr0 = GET_MSR (0);
1209
  if (GET_MSR_EMCI (msr0) == 0)
1210
    {
1211
      /* no interrupt queued at this time.  */
1212
      frv_set_mp_exception_registers (current_cpu, MTT_UNIMPLEMENTED_MPOP, 0);
1213
    }
1214
}
1215
 
1216
/* Simulate the media average (MAVEH) insn.  */
1217
static HI
1218
do_media_average (SIM_CPU *current_cpu, HI arg1, HI arg2)
1219
{
1220
  SIM_DESC sd = CPU_STATE (current_cpu);
1221
  SI sum = (arg1 + arg2);
1222
  HI result = sum >> 1;
1223
  int rounding_value;
1224
 
1225
  /* On fr4xx and fr550, check the rounding mode.  On other machines
1226
     rounding is always toward negative infinity and the result is
1227
     already correctly rounded.  */
1228
  switch (STATE_ARCHITECTURE (sd)->mach)
1229
    {
1230
      /* Need to check rounding mode. */
1231
    case bfd_mach_fr400:
1232
    case bfd_mach_fr450:
1233
    case bfd_mach_fr550:
1234
      /* Check whether rounding will be required.  Rounding will be required
1235
         if the sum is an odd number.  */
1236
      rounding_value = sum & 1;
1237
      if (rounding_value)
1238
        {
1239
          USI msr0 = GET_MSR (0);
1240
          /* Check MSR0.SRDAV to determine which bits control the rounding.  */
1241
          if (GET_MSR_SRDAV (msr0))
1242
            {
1243
              /* MSR0.RD controls rounding.  */
1244
              switch (GET_MSR_RD (msr0))
1245
                {
1246
                case 0:
1247
                  /* Round to nearest.  */
1248
                  if (result >= 0)
1249
                    ++result;
1250
                  break;
1251
                case 1:
1252
                  /* Round toward 0. */
1253
                  if (result < 0)
1254
                    ++result;
1255
                  break;
1256
                case 2:
1257
                  /* Round toward positive infinity.  */
1258
                  ++result;
1259
                  break;
1260
                case 3:
1261
                  /* Round toward negative infinity.  The result is already
1262
                     correctly rounded.  */
1263
                  break;
1264
                default:
1265
                  abort ();
1266
                  break;
1267
                }
1268
            }
1269
          else
1270
            {
1271
              /* MSR0.RDAV controls rounding.  If set, round toward positive
1272
                 infinity.  Otherwise the result is already rounded correctly
1273
                 toward negative infinity.  */
1274
              if (GET_MSR_RDAV (msr0))
1275
                ++result;
1276
            }
1277
        }
1278
      break;
1279
    default:
1280
      break;
1281
    }
1282
 
1283
  return result;
1284
}
1285
 
1286
SI
1287
frvbf_media_average (SIM_CPU *current_cpu, SI reg1, SI reg2)
1288
{
1289
  SI result;
1290
  result  = do_media_average (current_cpu, reg1 & 0xffff, reg2 & 0xffff);
1291
  result &= 0xffff;
1292
  result |= do_media_average (current_cpu, (reg1 >> 16) & 0xffff,
1293
                              (reg2 >> 16) & 0xffff) << 16;
1294
  return result;
1295
}
1296
 
1297
/* Maintain a flag in order to know when to write the address of the next
1298
   VLIW instruction into the LR register.  Used by JMPL. JMPIL, and CALL.  */
1299
void
1300
frvbf_set_write_next_vliw_addr_to_LR (SIM_CPU *current_cpu, int value)
1301
{
1302
  frvbf_write_next_vliw_addr_to_LR = value;
1303
}
1304
 
1305
void
1306
frvbf_set_ne_index (SIM_CPU *current_cpu, int index)
1307
{
1308
  USI NE_flags[2];
1309
 
1310
  /* Save the target register so interrupt processing can set its NE flag
1311
     in the event of an exception.  */
1312
  frv_interrupt_state.ne_index = index;
1313
 
1314
  /* Clear the NE flag of the target register. It will be reset if necessary
1315
     in the event of an exception.  */
1316
  GET_NE_FLAGS (NE_flags, H_SPR_FNER0);
1317
  CLEAR_NE_FLAG (NE_flags, index);
1318
  SET_NE_FLAGS (H_SPR_FNER0, NE_flags);
1319
}
1320
 
1321
void
1322
frvbf_force_update (SIM_CPU *current_cpu)
1323
{
1324
  CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (current_cpu);
1325
  int ix = CGEN_WRITE_QUEUE_INDEX (q);
1326
  if (ix > 0)
1327
    {
1328
      CGEN_WRITE_QUEUE_ELEMENT *item = CGEN_WRITE_QUEUE_ELEMENT (q, ix - 1);
1329
      item->flags |= FRV_WRITE_QUEUE_FORCE_WRITE;
1330
    }
1331
}
1332
 
1333
/* Condition code logic.  */
1334
enum cr_ops {
1335
  andcr, orcr, xorcr, nandcr, norcr, andncr, orncr, nandncr, norncr,
1336
  num_cr_ops
1337
};
1338
 
1339
enum cr_result {cr_undefined, cr_undefined1, cr_false, cr_true};
1340
 
1341
static enum cr_result
1342
cr_logic[num_cr_ops][4][4] = {
1343
  /* andcr */
1344
  {
1345
    /*                undefined     undefined       false         true */
1346
    /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1347
    /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1348
    /* false     */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1349
    /* true      */ {cr_undefined, cr_undefined, cr_false,     cr_true     }
1350
  },
1351
  /* orcr */
1352
  {
1353
    /*                undefined     undefined       false         true */
1354
    /* undefined */ {cr_undefined, cr_undefined, cr_false,     cr_true     },
1355
    /* undefined */ {cr_undefined, cr_undefined, cr_false,     cr_true     },
1356
    /* false     */ {cr_false,     cr_false,     cr_false,     cr_true     },
1357
    /* true      */ {cr_true,      cr_true,      cr_true,      cr_true     }
1358
  },
1359
  /* xorcr */
1360
  {
1361
    /*                undefined     undefined       false         true */
1362
    /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1363
    /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1364
    /* false     */ {cr_undefined, cr_undefined, cr_false,     cr_true     },
1365
    /* true      */ {cr_true,      cr_true,      cr_true,      cr_false    }
1366
  },
1367
  /* nandcr */
1368
  {
1369
    /*                undefined     undefined       false         true */
1370
    /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1371
    /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1372
    /* false     */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1373
    /* true      */ {cr_undefined, cr_undefined, cr_true,      cr_false    }
1374
  },
1375
  /* norcr */
1376
  {
1377
    /*                undefined     undefined       false         true */
1378
    /* undefined */ {cr_undefined, cr_undefined, cr_true,      cr_false    },
1379
    /* undefined */ {cr_undefined, cr_undefined, cr_true,      cr_false    },
1380
    /* false     */ {cr_true,      cr_true,      cr_true,      cr_false    },
1381
    /* true      */ {cr_false,     cr_false,     cr_false,     cr_false    }
1382
  },
1383
  /* andncr */
1384
  {
1385
    /*                undefined     undefined       false         true */
1386
    /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1387
    /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1388
    /* false     */ {cr_undefined, cr_undefined, cr_false,     cr_true     },
1389
    /* true      */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}
1390
  },
1391
  /* orncr */
1392
  {
1393
    /*                undefined     undefined       false         true */
1394
    /* undefined */ {cr_undefined, cr_undefined, cr_false,     cr_true     },
1395
    /* undefined */ {cr_undefined, cr_undefined, cr_false,     cr_true     },
1396
    /* false     */ {cr_true,      cr_true,      cr_true,      cr_true     },
1397
    /* true      */ {cr_false,     cr_false,     cr_false,     cr_true     }
1398
  },
1399
  /* nandncr */
1400
  {
1401
    /*                undefined     undefined       false         true */
1402
    /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1403
    /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1404
    /* false     */ {cr_undefined, cr_undefined, cr_true,      cr_false    },
1405
    /* true      */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}
1406
  },
1407
  /* norncr */
1408
  {
1409
    /*                undefined     undefined       false         true */
1410
    /* undefined */ {cr_undefined, cr_undefined, cr_true,      cr_false    },
1411
    /* undefined */ {cr_undefined, cr_undefined, cr_true,      cr_false    },
1412
    /* false     */ {cr_false,     cr_false,     cr_false,     cr_false    },
1413
    /* true      */ {cr_true,      cr_true,      cr_true,      cr_false    }
1414
  }
1415
};
1416
 
1417
UQI
1418
frvbf_cr_logic (SIM_CPU *current_cpu, SI operation, UQI arg1, UQI arg2)
1419
{
1420
  return cr_logic[operation][arg1][arg2];
1421
}
1422
 
1423
/* Cache Manipulation.  */
1424
void
1425
frvbf_insn_cache_preload (SIM_CPU *current_cpu, SI address, USI length, int lock)
1426
{
1427
  /* If we need to count cycles, then the cache operation will be
1428
     initiated from the model profiling functions.
1429
     See frvbf_model_....  */
1430
  int hsr0 = GET_HSR0 ();
1431
  if (GET_HSR0_ICE (hsr0))
1432
    {
1433
      if (model_insn)
1434
        {
1435
          CPU_LOAD_ADDRESS (current_cpu) = address;
1436
          CPU_LOAD_LENGTH (current_cpu) = length;
1437
          CPU_LOAD_LOCK (current_cpu) = lock;
1438
        }
1439
      else
1440
        {
1441
          FRV_CACHE *cache = CPU_INSN_CACHE (current_cpu);
1442
          frv_cache_preload (cache, address, length, lock);
1443
        }
1444
    }
1445
}
1446
 
1447
void
1448
frvbf_data_cache_preload (SIM_CPU *current_cpu, SI address, USI length, int lock)
1449
{
1450
  /* If we need to count cycles, then the cache operation will be
1451
     initiated from the model profiling functions.
1452
     See frvbf_model_....  */
1453
  int hsr0 = GET_HSR0 ();
1454
  if (GET_HSR0_DCE (hsr0))
1455
    {
1456
      if (model_insn)
1457
        {
1458
          CPU_LOAD_ADDRESS (current_cpu) = address;
1459
          CPU_LOAD_LENGTH (current_cpu) = length;
1460
          CPU_LOAD_LOCK (current_cpu) = lock;
1461
        }
1462
      else
1463
        {
1464
          FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
1465
          frv_cache_preload (cache, address, length, lock);
1466
        }
1467
    }
1468
}
1469
 
1470
void
1471
frvbf_insn_cache_unlock (SIM_CPU *current_cpu, SI address)
1472
{
1473
  /* If we need to count cycles, then the cache operation will be
1474
     initiated from the model profiling functions.
1475
     See frvbf_model_....  */
1476
  int hsr0 = GET_HSR0 ();
1477
  if (GET_HSR0_ICE (hsr0))
1478
    {
1479
      if (model_insn)
1480
        CPU_LOAD_ADDRESS (current_cpu) = address;
1481
      else
1482
        {
1483
          FRV_CACHE *cache = CPU_INSN_CACHE (current_cpu);
1484
          frv_cache_unlock (cache, address);
1485
        }
1486
    }
1487
}
1488
 
1489
void
1490
frvbf_data_cache_unlock (SIM_CPU *current_cpu, SI address)
1491
{
1492
  /* If we need to count cycles, then the cache operation will be
1493
     initiated from the model profiling functions.
1494
     See frvbf_model_....  */
1495
  int hsr0 = GET_HSR0 ();
1496
  if (GET_HSR0_DCE (hsr0))
1497
    {
1498
      if (model_insn)
1499
        CPU_LOAD_ADDRESS (current_cpu) = address;
1500
      else
1501
        {
1502
          FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
1503
          frv_cache_unlock (cache, address);
1504
        }
1505
    }
1506
}
1507
 
1508
void
1509
frvbf_insn_cache_invalidate (SIM_CPU *current_cpu, SI address, int all)
1510
{
1511
  /* Make sure the insn was specified properly.  -1 will be passed for ALL
1512
     for a icei with A=0.  */
1513
  if (all == -1)
1514
    {
1515
      frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
1516
      return;
1517
    }
1518
 
1519
  /* If we need to count cycles, then the cache operation will be
1520
     initiated from the model profiling functions.
1521
     See frvbf_model_....  */
1522
  if (model_insn)
1523
    {
1524
      /* Record the all-entries flag for use in profiling.  */
1525
      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu);
1526
      ps->all_cache_entries = all;
1527
      CPU_LOAD_ADDRESS (current_cpu) = address;
1528
    }
1529
  else
1530
    {
1531
      FRV_CACHE *cache = CPU_INSN_CACHE (current_cpu);
1532
      if (all)
1533
        frv_cache_invalidate_all (cache, 0/* flush? */);
1534
      else
1535
        frv_cache_invalidate (cache, address, 0/* flush? */);
1536
    }
1537
}
1538
 
1539
void
1540
frvbf_data_cache_invalidate (SIM_CPU *current_cpu, SI address, int all)
1541
{
1542
  /* Make sure the insn was specified properly.  -1 will be passed for ALL
1543
     for a dcei with A=0.  */
1544
  if (all == -1)
1545
    {
1546
      frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
1547
      return;
1548
    }
1549
 
1550
  /* If we need to count cycles, then the cache operation will be
1551
     initiated from the model profiling functions.
1552
     See frvbf_model_....  */
1553
  if (model_insn)
1554
    {
1555
      /* Record the all-entries flag for use in profiling.  */
1556
      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu);
1557
      ps->all_cache_entries = all;
1558
      CPU_LOAD_ADDRESS (current_cpu) = address;
1559
    }
1560
  else
1561
    {
1562
      FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
1563
      if (all)
1564
        frv_cache_invalidate_all (cache, 0/* flush? */);
1565
      else
1566
        frv_cache_invalidate (cache, address, 0/* flush? */);
1567
    }
1568
}
1569
 
1570
void
1571
frvbf_data_cache_flush (SIM_CPU *current_cpu, SI address, int all)
1572
{
1573
  /* Make sure the insn was specified properly.  -1 will be passed for ALL
1574
     for a dcef with A=0.  */
1575
  if (all == -1)
1576
    {
1577
      frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
1578
      return;
1579
    }
1580
 
1581
  /* If we need to count cycles, then the cache operation will be
1582
     initiated from the model profiling functions.
1583
     See frvbf_model_....  */
1584
  if (model_insn)
1585
    {
1586
      /* Record the all-entries flag for use in profiling.  */
1587
      FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu);
1588
      ps->all_cache_entries = all;
1589
      CPU_LOAD_ADDRESS (current_cpu) = address;
1590
    }
1591
  else
1592
    {
1593
      FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
1594
      if (all)
1595
        frv_cache_invalidate_all (cache, 1/* flush? */);
1596
      else
1597
        frv_cache_invalidate (cache, address, 1/* flush? */);
1598
    }
1599
}

powered by: WebSVN 2.1.0

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