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