]> Git Repo - binutils.git/blob - sim/frv/traps.c
Automatic date update in version.in
[binutils.git] / sim / frv / traps.c
1 /* frv trap support
2    Copyright (C) 1999-2022 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 frvbf
24 #define WANT_CPU_FRVBF
25
26 #include "sim-main.h"
27 #include "cgen-engine.h"
28 #include "cgen-par.h"
29 #include "sim-fpu.h"
30 #include "sim-signal.h"
31 #include "sim/callback.h"
32
33 #include "bfd.h"
34 #include "libiberty.h"
35
36 #include <stdlib.h>
37
38 CGEN_ATTR_VALUE_ENUM_TYPE frv_current_fm_slot;
39
40 /* The semantic code invokes this for invalid (unrecognized) instructions.  */
41
42 SEM_PC
43 sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc)
44 {
45   frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
46   return vpc;
47 }
48
49 /* Process an address exception.  */
50
51 void
52 frv_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia,
53                   unsigned int map, int nr_bytes, address_word addr,
54                   transfer_type transfer, sim_core_signals sig)
55 {
56   if (sig == sim_core_unaligned_signal)
57     {
58       if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400
59           || STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450)
60         frv_queue_data_access_error_interrupt (current_cpu, addr);
61       else
62         frv_queue_mem_address_not_aligned_interrupt (current_cpu, addr);
63     }
64
65   frv_term (sd);
66   sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr, transfer, sig);
67 }
68
69 void
70 frv_sim_engine_halt_hook (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia)
71 {
72   int i;
73   if (current_cpu != NULL)
74     CPU_PC_SET (current_cpu, cia);
75
76   /* Invalidate the insn and data caches of all cpus.  */
77   for (i = 0; i < MAX_NR_PROCESSORS; ++i)
78     {
79       current_cpu = STATE_CPU (sd, i);
80       frv_cache_invalidate_all (CPU_INSN_CACHE (current_cpu), 0);
81       frv_cache_invalidate_all (CPU_DATA_CACHE (current_cpu), 1);
82     }
83   frv_term (sd);
84 }
85 \f
86 /* Read/write functions for system call interface.  */
87
88 static int
89 syscall_read_mem (host_callback *cb, struct cb_syscall *sc,
90                   unsigned long taddr, char *buf, int bytes)
91 {
92   SIM_DESC sd = (SIM_DESC) sc->p1;
93   SIM_CPU *cpu = (SIM_CPU *) sc->p2;
94
95   frv_cache_invalidate_all (CPU_DATA_CACHE (cpu), 1);
96   return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes);
97 }
98
99 static int
100 syscall_write_mem (host_callback *cb, struct cb_syscall *sc,
101                    unsigned long taddr, const char *buf, int bytes)
102 {
103   SIM_DESC sd = (SIM_DESC) sc->p1;
104   SIM_CPU *cpu = (SIM_CPU *) sc->p2;
105
106   frv_cache_invalidate_all (CPU_INSN_CACHE (cpu), 0);
107   frv_cache_invalidate_all (CPU_DATA_CACHE (cpu), 1);
108   return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes);
109 }
110
111 /* Handle TRA and TIRA insns.  */
112 void
113 frv_itrap (SIM_CPU *current_cpu, PCADDR pc, USI base, SI offset)
114 {
115   SIM_DESC sd = CPU_STATE (current_cpu);
116   host_callback *cb = STATE_CALLBACK (sd);
117   USI num = ((base + offset) & 0x7f) + 0x80;
118
119   if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)
120     {
121       frv_queue_software_interrupt (current_cpu, num);
122       return;
123     }
124
125   switch (num)
126     {
127     case TRAP_SYSCALL :
128       {
129         CB_SYSCALL s;
130         CB_SYSCALL_INIT (&s);
131         s.func = GET_H_GR (7);
132         s.arg1 = GET_H_GR (8);
133         s.arg2 = GET_H_GR (9);
134         s.arg3 = GET_H_GR (10);
135
136         if (cb_target_to_host_syscall (cb, s.func) == CB_SYS_exit)
137           {
138             sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, s.arg1);
139           }
140
141         s.p1 = sd;
142         s.p2 = current_cpu;
143         s.read_mem = syscall_read_mem;
144         s.write_mem = syscall_write_mem;
145         cb_syscall (cb, &s);
146         SET_H_GR (8, s.result);
147         SET_H_GR (9, s.result2);
148         SET_H_GR (10, s.errcode);
149         break;
150       }
151
152     case TRAP_BREAKPOINT:
153       sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
154       break;
155
156       /* Add support for dumping registers, either at fixed traps, or all
157          unknown traps if configured with --enable-sim-trapdump.  */
158     default:
159 #if !TRAPDUMP
160       frv_queue_software_interrupt (current_cpu, num);
161       return;
162 #endif
163
164 #ifdef TRAP_REGDUMP1
165     case TRAP_REGDUMP1:
166 #endif
167
168 #ifdef TRAP_REGDUMP2
169     case TRAP_REGDUMP2:
170 #endif
171
172 #if TRAPDUMP || (defined (TRAP_REGDUMP1)) || (defined (TRAP_REGDUMP2))
173       {
174         char buf[256];
175         int i, j;
176
177         buf[0] = 0;
178         if (STATE_TEXT_SECTION (sd)
179             && pc >= STATE_TEXT_START (sd)
180             && pc < STATE_TEXT_END (sd))
181           {
182             const char *pc_filename = (const char *)0;
183             const char *pc_function = (const char *)0;
184             unsigned int pc_linenum = 0;
185
186             if (bfd_find_nearest_line (STATE_PROG_BFD (sd),
187                                        STATE_TEXT_SECTION (sd),
188                                        (struct bfd_symbol **) 0,
189                                        pc - STATE_TEXT_START (sd),
190                                        &pc_filename, &pc_function, &pc_linenum)
191                 && (pc_function || pc_filename))
192               {
193                 char *p = buf+2;
194                 buf[0] = ' ';
195                 buf[1] = '(';
196                 if (pc_function)
197                   {
198                     strcpy (p, pc_function);
199                     p += strlen (p);
200                   }
201                 else
202                   {
203                     char *q = (char *) strrchr (pc_filename, '/');
204                     strcpy (p, (q) ? q+1 : pc_filename);
205                     p += strlen (p);
206                   }
207
208                 if (pc_linenum)
209                   {
210                     sprintf (p, " line %d", pc_linenum);
211                     p += strlen (p);
212                   }
213
214                 p[0] = ')';
215                 p[1] = '\0';
216                 if ((p+1) - buf > sizeof (buf))
217                   abort ();
218               }
219           }
220
221         sim_io_printf (sd,
222                        "\nRegister dump,    pc = 0x%.8x%s, base = %u, offset = %d\n",
223                        (unsigned)pc, buf, (unsigned)base, (int)offset);
224
225         for (i = 0; i < 64; i += 8)
226           {
227             long g0 = (long)GET_H_GR (i);
228             long g1 = (long)GET_H_GR (i+1);
229             long g2 = (long)GET_H_GR (i+2);
230             long g3 = (long)GET_H_GR (i+3);
231             long g4 = (long)GET_H_GR (i+4);
232             long g5 = (long)GET_H_GR (i+5);
233             long g6 = (long)GET_H_GR (i+6);
234             long g7 = (long)GET_H_GR (i+7);
235
236             if ((g0 | g1 | g2 | g3 | g4 | g5 | g6 | g7) != 0)
237               sim_io_printf (sd,
238                              "\tgr%02d - gr%02d:   0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx\n",
239                              i, i+7, g0, g1, g2, g3, g4, g5, g6, g7);
240           }
241
242         for (i = 0; i < 64; i += 8)
243           {
244             long f0 = (long)GET_H_FR (i);
245             long f1 = (long)GET_H_FR (i+1);
246             long f2 = (long)GET_H_FR (i+2);
247             long f3 = (long)GET_H_FR (i+3);
248             long f4 = (long)GET_H_FR (i+4);
249             long f5 = (long)GET_H_FR (i+5);
250             long f6 = (long)GET_H_FR (i+6);
251             long f7 = (long)GET_H_FR (i+7);
252
253             if ((f0 | f1 | f2 | f3 | f4 | f5 | f6 | f7) != 0)
254               sim_io_printf (sd,
255                              "\tfr%02d - fr%02d:   0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx\n",
256                              i, i+7, f0, f1, f2, f3, f4, f5, f6, f7);
257           }
258
259         sim_io_printf (sd,
260                        "\tlr/lcr/cc/ccc: 0x%.8lx 0x%.8lx 0x%.8lx 0x%.8lx\n",
261                        (long)GET_H_SPR (272),
262                        (long)GET_H_SPR (273),
263                        (long)GET_H_SPR (256),
264                        (long)GET_H_SPR (263));
265       }
266       break;
267 #endif
268     }
269 }
270
271 /* Handle the MTRAP insn.  */
272 void
273 frv_mtrap (SIM_CPU *current_cpu)
274 {
275   SIM_DESC sd = CPU_STATE (current_cpu);
276
277   /* Check the status of media exceptions in MSR0.  */
278   SI msr = GET_MSR (0);
279   if (GET_MSR_AOVF (msr)
280       || (GET_MSR_MTT (msr) && STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550))
281     frv_queue_program_interrupt (current_cpu, FRV_MP_EXCEPTION);
282 }
283
284 /* Handle the BREAK insn.  */
285 void
286 frv_break (SIM_CPU *current_cpu)
287 {
288   SIM_DESC sd = CPU_STATE (current_cpu);
289
290   if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
291     {
292       /* Invalidate the insn cache because the debugger will presumably
293          replace the breakpoint insn with the real one.  */
294       sim_engine_halt (sd, current_cpu, NULL, NULL_CIA, sim_stopped,
295                        SIM_SIGTRAP);
296     }
297
298   frv_queue_break_interrupt (current_cpu);
299 }
300
301 /* Return from trap.  */
302 USI
303 frv_rett (SIM_CPU *current_cpu, PCADDR pc, BI debug_field)
304 {
305   USI new_pc;
306   /* if (normal running mode and debug_field==0
307        PC=PCSR
308        PSR.ET=1
309        PSR.S=PSR.PS
310      else if (debug running mode and debug_field==1)
311        PC=(BPCSR)
312        PSR.ET=BPSR.BET
313        PSR.S=BPSR.BS
314        change to normal running mode
315   */
316   int psr_s = GET_H_PSR_S ();
317   int psr_et = GET_H_PSR_ET ();
318
319   /* Check for exceptions in the priority order listed in the FRV Architecture
320      Volume 2.  */
321   if (! psr_s)
322     {
323       /* Halt if PSR.ET is not set.  See chapter 6 of the LSI.  */
324       if (! psr_et)
325         {
326           SIM_DESC sd = CPU_STATE (current_cpu);
327           sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
328         }
329
330       /* privileged_instruction interrupt will have already been queued by
331          frv_detect_insn_access_interrupts.  */
332       new_pc = pc + 4;
333     }
334   else if (psr_et)
335     {
336       /* Halt if PSR.S is set.  See chapter 6 of the LSI.  */
337       if (psr_s)
338         {
339           SIM_DESC sd = CPU_STATE (current_cpu);
340           sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
341         }
342
343       frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
344       new_pc = pc + 4;
345     }
346   else if (! CPU_DEBUG_STATE (current_cpu) && debug_field == 0)
347     {
348       USI psr = GET_PSR ();
349       /* Return from normal running state.  */
350       new_pc = GET_H_SPR (H_SPR_PCSR);
351       SET_PSR_ET (psr, 1);
352       SET_PSR_S (psr, GET_PSR_PS (psr));
353       sim_queue_fn_si_write (current_cpu, frvbf_h_spr_set, H_SPR_PSR, psr);
354     }
355   else if (CPU_DEBUG_STATE (current_cpu) && debug_field == 1)
356     {
357       USI psr = GET_PSR ();
358       /* Return from debug state.  */
359       new_pc = GET_H_SPR (H_SPR_BPCSR);
360       SET_PSR_ET (psr, GET_H_BPSR_BET ());
361       SET_PSR_S (psr, GET_H_BPSR_BS ());
362       sim_queue_fn_si_write (current_cpu, frvbf_h_spr_set, H_SPR_PSR, psr);
363       CPU_DEBUG_STATE (current_cpu) = 0;
364     }
365   else
366     new_pc = pc + 4;
367
368   return new_pc;
369 }
370 \f
371 /* Functions for handling non-excepting instruction side effects.  */
372 static SI next_available_nesr (SIM_CPU *current_cpu, SI current_index)
373 {
374   FRV_REGISTER_CONTROL *control = CPU_REGISTER_CONTROL (current_cpu);
375   if (control->spr[H_SPR_NECR].implemented)
376     {
377       int limit;
378       USI necr = GET_NECR ();
379
380       /* See if any NESRs are implemented. First need to check the validity of
381          the NECR.  */
382       if (! GET_NECR_VALID (necr))
383         return NO_NESR;
384
385       limit = GET_NECR_NEN (necr);
386       for (++current_index; current_index < limit; ++current_index)
387         {
388           SI nesr = GET_NESR (current_index);
389           if (! GET_NESR_VALID (nesr))
390             return current_index;
391         }
392     }
393   return NO_NESR;
394 }
395
396 static SI next_valid_nesr (SIM_CPU *current_cpu, SI current_index)
397 {
398   FRV_REGISTER_CONTROL *control = CPU_REGISTER_CONTROL (current_cpu);
399   if (control->spr[H_SPR_NECR].implemented)
400     {
401       int limit;
402       USI necr = GET_NECR ();
403
404       /* See if any NESRs are implemented. First need to check the validity of
405          the NECR.  */
406       if (! GET_NECR_VALID (necr))
407         return NO_NESR;
408
409       limit = GET_NECR_NEN (necr);
410       for (++current_index; current_index < limit; ++current_index)
411         {
412           SI nesr = GET_NESR (current_index);
413           if (GET_NESR_VALID (nesr))
414             return current_index;
415         }
416     }
417   return NO_NESR;
418 }
419
420 BI
421 frvbf_check_non_excepting_load (
422   SIM_CPU *current_cpu, SI base_index, SI disp_index, SI target_index,
423   SI immediate_disp, QI data_size, BI is_float
424 )
425 {
426   BI rc = 1; /* perform the load.  */
427   SIM_DESC sd = CPU_STATE (current_cpu);
428   int daec = 0;
429   int rec  = 0;
430   int ec   = 0;
431   USI necr;
432   int do_elos;
433   SI NE_flags[2];
434   SI NE_base;
435   SI nesr;
436   SI ne_index;
437   FRV_REGISTER_CONTROL *control;
438
439   SI address = GET_H_GR (base_index);
440   if (disp_index >= 0)
441     address += GET_H_GR (disp_index);
442   else
443     address += immediate_disp;
444
445   /* Check for interrupt factors.  */
446   switch (data_size)
447     {
448     case NESR_UQI_SIZE:
449     case NESR_QI_SIZE:
450       break;
451     case NESR_UHI_SIZE:
452     case NESR_HI_SIZE:
453       if (address & 1)
454         ec = 1;
455       break;
456     case NESR_SI_SIZE:
457       if (address & 3)
458         ec = 1;
459       break;
460     case NESR_DI_SIZE:
461       if (address & 7)
462         ec = 1;
463       if (target_index & 1)
464         rec = 1;
465       break;
466     case NESR_XI_SIZE:
467       if (address & 0xf)
468         ec = 1;
469       if (target_index & 3)
470         rec = 1;
471       break;
472     default:
473       {
474         IADDR pc = GET_H_PC ();
475         sim_engine_abort (sd, current_cpu, pc, 
476                           "check_non_excepting_load: Incorrect data_size\n");
477         break;
478       }
479     }
480
481   control = CPU_REGISTER_CONTROL (current_cpu);
482   if (control->spr[H_SPR_NECR].implemented)
483     {
484       necr = GET_NECR ();
485       do_elos = GET_NECR_VALID (necr) && GET_NECR_ELOS (necr);
486     }
487   else
488     do_elos = 0;
489
490   /* NECR, NESR, NEEAR are only implemented for the full frv machine.  */
491   if (do_elos)
492     {
493       ne_index = next_available_nesr (current_cpu, NO_NESR);
494       if (ne_index == NO_NESR)
495         {
496           IADDR pc = GET_H_PC ();
497           sim_engine_abort (sd, current_cpu, pc, 
498                             "No available NESR register\n");
499         }
500
501       /* Fill in the basic fields of the NESR.  */
502       nesr = GET_NESR (ne_index);
503       SET_NESR_VALID (nesr);
504       SET_NESR_EAV (nesr);
505       SET_NESR_DRN (nesr, target_index);
506       SET_NESR_SIZE (nesr, data_size);
507       SET_NESR_NEAN (nesr, ne_index);
508       if (is_float)
509         SET_NESR_FR (nesr);
510       else
511         CLEAR_NESR_FR (nesr);
512
513       /* Set the corresponding NEEAR.  */
514       SET_NEEAR (ne_index, address);
515   
516       SET_NESR_DAEC (nesr, 0);
517       SET_NESR_REC (nesr, 0);
518       SET_NESR_EC (nesr, 0);
519     }
520
521   /* Set the NE flag corresponding to the target register if an interrupt
522      factor was detected. 
523      daec is not checked here yet, but is declared for future reference.  */
524   if (is_float)
525     NE_base = H_SPR_FNER0;
526   else
527     NE_base = H_SPR_GNER0;
528
529   GET_NE_FLAGS (NE_flags, NE_base);
530   if (rec)
531     {
532       SET_NE_FLAG (NE_flags, target_index);
533       if (do_elos)
534         SET_NESR_REC (nesr, NESR_REGISTER_NOT_ALIGNED);
535     }
536
537   if (ec)
538     {
539       SET_NE_FLAG (NE_flags, target_index);
540       if (do_elos)
541         SET_NESR_EC (nesr, NESR_MEM_ADDRESS_NOT_ALIGNED);
542     }
543
544   if (do_elos)
545     SET_NESR (ne_index, nesr);
546
547   /* If no interrupt factor was detected then set the NE flag on the
548      target register if the NE flag on one of the input registers
549      is already set.  */
550   if (! rec && ! ec && ! daec)
551     {
552       BI ne_flag = GET_NE_FLAG (NE_flags, base_index);
553       if (disp_index >= 0)
554         ne_flag |= GET_NE_FLAG (NE_flags, disp_index);
555       if (ne_flag)
556         {
557           SET_NE_FLAG (NE_flags, target_index);
558           rc = 0; /* Do not perform the load.  */
559         }
560       else
561         CLEAR_NE_FLAG (NE_flags, target_index);
562     }
563
564   SET_NE_FLAGS (NE_base, NE_flags);
565
566   return rc; /* perform the load?  */
567 }
568
569 /* Record state for media exception: media_cr_not_aligned.  */
570 void
571 frvbf_media_cr_not_aligned (SIM_CPU *current_cpu)
572 {
573   SIM_DESC sd = CPU_STATE (current_cpu);
574
575   /* On some machines this generates an illegal_instruction interrupt.  */
576   switch (STATE_ARCHITECTURE (sd)->mach)
577     {
578       /* Note: there is a discrepancy between V2.2 of the FR400
579          instruction manual and the various FR4xx LSI specs.  The former
580          claims that unaligned registers cause an mp_exception while the
581          latter say it's an illegal_instruction.  The LSI specs appear
582          to be correct since MTT is fixed at 1.  */
583     case bfd_mach_fr400:
584     case bfd_mach_fr450:
585     case bfd_mach_fr550:
586       frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
587       break;
588     default:
589       frv_set_mp_exception_registers (current_cpu, MTT_CR_NOT_ALIGNED, 0);
590       break;
591     }
592 }
593
594 /* Record state for media exception: media_acc_not_aligned.  */
595 void
596 frvbf_media_acc_not_aligned (SIM_CPU *current_cpu)
597 {
598   SIM_DESC sd = CPU_STATE (current_cpu);
599
600   /* On some machines this generates an illegal_instruction interrupt.  */
601   switch (STATE_ARCHITECTURE (sd)->mach)
602     {
603       /* See comment in frvbf_cr_not_aligned().  */
604     case bfd_mach_fr400:
605     case bfd_mach_fr450:
606     case bfd_mach_fr550:
607       frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
608       break;
609     default:
610       frv_set_mp_exception_registers (current_cpu, MTT_ACC_NOT_ALIGNED, 0);
611       break;
612     }
613 }
614
615 /* Record state for media exception: media_register_not_aligned.  */
616 void
617 frvbf_media_register_not_aligned (SIM_CPU *current_cpu)
618 {
619   SIM_DESC sd = CPU_STATE (current_cpu);
620
621   /* On some machines this generates an illegal_instruction interrupt.  */
622   switch (STATE_ARCHITECTURE (sd)->mach)
623     {
624       /* See comment in frvbf_cr_not_aligned().  */
625     case bfd_mach_fr400:
626     case bfd_mach_fr450:
627     case bfd_mach_fr550:
628       frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
629       break;
630     default:
631       frv_set_mp_exception_registers (current_cpu, MTT_INVALID_FR, 0);
632       break;
633     }
634 }
635
636 /* Record state for media exception: media_overflow.  */
637 void
638 frvbf_media_overflow (SIM_CPU *current_cpu, int sie)
639 {
640   frv_set_mp_exception_registers (current_cpu, MTT_OVERFLOW, sie);
641 }
642
643 /* Queue a division exception.  */
644 enum frv_dtt
645 frvbf_division_exception (SIM_CPU *current_cpu, enum frv_dtt dtt,
646                           int target_index, int non_excepting)
647 {
648   /* If there was an overflow and it is masked, then record it in
649      ISR.AEXC.  */
650   USI isr = GET_ISR ();
651   if ((dtt & FRV_DTT_OVERFLOW) && GET_ISR_EDE (isr))
652     {
653       dtt &= ~FRV_DTT_OVERFLOW;
654       SET_ISR_AEXC (isr);
655       SET_ISR (isr);
656     }
657   if (dtt != FRV_DTT_NO_EXCEPTION)
658     {
659       if (non_excepting)
660         {
661           /* Non excepting instruction, simply set the NE flag for the target
662              register.  */
663           SI NE_flags[2];
664           GET_NE_FLAGS (NE_flags, H_SPR_GNER0);
665           SET_NE_FLAG (NE_flags, target_index);
666           SET_NE_FLAGS (H_SPR_GNER0, NE_flags);
667         }
668       else
669         frv_queue_division_exception_interrupt (current_cpu, dtt);
670     }
671   return dtt;
672 }
673
674 void
675 frvbf_check_recovering_store (
676   SIM_CPU *current_cpu, PCADDR address, SI regno, int size, int is_float
677 )
678 {
679   FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
680   int reg_ix;
681
682   CPU_RSTR_INVALIDATE(current_cpu) = 0;
683
684   for (reg_ix = next_valid_nesr (current_cpu, NO_NESR);
685        reg_ix != NO_NESR;
686        reg_ix = next_valid_nesr (current_cpu, reg_ix))
687     {
688       if (address == GET_H_SPR (H_SPR_NEEAR0 + reg_ix))
689         {
690           SI nesr = GET_NESR (reg_ix);
691           int nesr_drn = GET_NESR_DRN (nesr);
692           BI nesr_fr = GET_NESR_FR (nesr);
693           SI remain;
694
695           /* Invalidate cache block containing this address.
696              If we need to count cycles, then the cache operation will be
697              initiated from the model profiling functions.
698              See frvbf_model_....  */
699           if (model_insn)
700             {
701               CPU_RSTR_INVALIDATE(current_cpu) = 1;
702               CPU_LOAD_ADDRESS (current_cpu) = address;
703             }
704           else
705             frv_cache_invalidate (cache, address, 1/* flush */);
706
707           /* Copy the stored value to the register indicated by NESR.DRN.  */
708           for (remain = size; remain > 0; remain -= 4)
709             {
710               SI value;
711
712               if (is_float)
713                 value = GET_H_FR (regno);
714               else
715                 value = GET_H_GR (regno);
716
717               switch (size)
718                 {
719                 case 1:
720                   value &= 0xff;
721                   break;
722                 case 2:
723                   value &= 0xffff;
724                   break;
725                 default:
726                   break;
727                 }
728
729               if (nesr_fr)
730                 sim_queue_fn_sf_write (current_cpu, frvbf_h_fr_set, nesr_drn,
731                                        value);
732               else
733                 sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, nesr_drn,
734                                        value);
735
736               nesr_drn++;
737               regno++;
738             }
739           break; /* Only consider the first matching register.  */
740         }
741     } /* loop over active neear registers.  */
742 }
743
744 SI
745 frvbf_check_acc_range (SIM_CPU *current_cpu, SI regno)
746 {
747   /* Only applicable to fr550 */
748   SIM_DESC sd = CPU_STATE (current_cpu);
749   if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550)
750     return 0;
751
752   /* On the fr550, media insns in slots 0 and 2 can only access
753      accumulators acc0-acc3. Insns in slots 1 and 3 can only access
754      accumulators acc4-acc7 */
755   switch (frv_current_fm_slot)
756     {
757     case UNIT_FM0:
758     case UNIT_FM2:
759       if (regno <= 3)
760         return 1; /* all is ok */
761       break;
762     case UNIT_FM1:
763     case UNIT_FM3:
764       if (regno >= 4)
765         return 1; /* all is ok */
766       break;
767     }
768   
769   /* The specified accumulator is out of range. Queue an illegal_instruction
770      interrupt.  */
771   frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
772   return 0;
773 }
774
775 void
776 frvbf_check_swap_address (SIM_CPU *current_cpu, SI address)
777 {
778   /* Only applicable to fr550 */
779   SIM_DESC sd = CPU_STATE (current_cpu);
780   if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550)
781     return;
782
783   /* Adress must be aligned on a word boundary.  */
784   if (address & 0x3)
785     frv_queue_data_access_exception_interrupt (current_cpu);
786 }
787
788 static void
789 clear_nesr_neear (SIM_CPU *current_cpu, SI target_index, BI is_float)
790 {
791   int reg_ix;
792
793   /* Only implemented for full frv.  */
794   SIM_DESC sd = CPU_STATE (current_cpu);
795   if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_frv)
796     return;
797
798   /* Clear the appropriate NESR and NEEAR registers.  */
799   for (reg_ix = next_valid_nesr (current_cpu, NO_NESR);
800        reg_ix != NO_NESR;
801        reg_ix = next_valid_nesr (current_cpu, reg_ix))
802     {
803       SI nesr;
804       /* The register is available, now check if it is active.  */
805       nesr = GET_NESR (reg_ix);
806       if (GET_NESR_FR (nesr) == is_float)
807         {
808           if (target_index < 0 || GET_NESR_DRN (nesr) == target_index)
809             {
810               SET_NESR (reg_ix, 0);
811               SET_NEEAR (reg_ix, 0);
812             }
813         }
814     }
815 }
816
817 static void
818 clear_ne_flags (
819   SIM_CPU *current_cpu,
820   SI target_index,
821   int hi_available,
822   int lo_available,
823   SI NE_base
824 )
825 {
826   SI NE_flags[2];
827   int exception;
828
829   GET_NE_FLAGS (NE_flags, NE_base);
830   if (target_index >= 0)
831     CLEAR_NE_FLAG (NE_flags, target_index);
832   else
833     {
834       if (lo_available)
835         NE_flags[1] = 0;
836       if (hi_available)
837         NE_flags[0] = 0;
838     }
839   SET_NE_FLAGS (NE_base, NE_flags);
840 }
841
842 /* Return 1 if the given register is available, 0 otherwise.  TARGET_INDEX==-1
843    means to check for any register available.  */
844 static void
845 which_registers_available (
846   SIM_CPU *current_cpu, int *hi_available, int *lo_available, int is_float
847 )
848 {
849   if (is_float)
850     frv_fr_registers_available (current_cpu, hi_available, lo_available);
851   else
852     frv_gr_registers_available (current_cpu, hi_available, lo_available);
853 }
854
855 void
856 frvbf_clear_ne_flags (SIM_CPU *current_cpu, SI target_index, BI is_float)
857 {
858   int hi_available;
859   int lo_available;
860   int exception;
861   SI NE_base;
862   USI necr;
863   FRV_REGISTER_CONTROL *control;
864
865   /* Check for availability of the target register(s).  */
866   which_registers_available (current_cpu, & hi_available, & lo_available,
867                              is_float);
868
869   /* Check to make sure that the target register is available.  */
870   if (! frv_check_register_access (current_cpu, target_index,
871                                    hi_available, lo_available))
872     return;
873
874   /* Determine whether we're working with GR or FR registers.  */
875   if (is_float)
876     NE_base = H_SPR_FNER0;
877   else
878     NE_base = H_SPR_GNER0;
879
880   /* Always clear the appropriate NE flags.  */
881   clear_ne_flags (current_cpu, target_index, hi_available, lo_available,
882                   NE_base);
883
884   /* Clear the appropriate NESR and NEEAR registers.  */
885   control = CPU_REGISTER_CONTROL (current_cpu);
886   if (control->spr[H_SPR_NECR].implemented)
887     {
888       necr = GET_NECR ();
889       if (GET_NECR_VALID (necr) && GET_NECR_ELOS (necr))
890         clear_nesr_neear (current_cpu, target_index, is_float);
891     }
892 }
893
894 void
895 frvbf_commit (SIM_CPU *current_cpu, SI target_index, BI is_float)
896 {
897   SI NE_base;
898   SI NE_flags[2];
899   BI NE_flag;
900   int exception;
901   int hi_available;
902   int lo_available;
903   USI necr;
904   FRV_REGISTER_CONTROL *control;
905
906   /* Check for availability of the target register(s).  */
907   which_registers_available (current_cpu, & hi_available, & lo_available,
908                              is_float);
909
910   /* Check to make sure that the target register is available.  */
911   if (! frv_check_register_access (current_cpu, target_index,
912                                    hi_available, lo_available))
913     return;
914
915   /* Determine whether we're working with GR or FR registers.  */
916   if (is_float)
917     NE_base = H_SPR_FNER0;
918   else
919     NE_base = H_SPR_GNER0;
920
921   /* Determine whether a ne exception is pending.  */
922   GET_NE_FLAGS (NE_flags, NE_base);
923   if (target_index >= 0)
924     NE_flag = GET_NE_FLAG (NE_flags, target_index);
925   else
926     {
927       NE_flag = (hi_available && NE_flags[0] != 0)
928                 || (lo_available && NE_flags[1] != 0);
929     }
930
931   /* Always clear the appropriate NE flags.  */
932   clear_ne_flags (current_cpu, target_index, hi_available, lo_available,
933                   NE_base);
934
935   control = CPU_REGISTER_CONTROL (current_cpu);
936   if (control->spr[H_SPR_NECR].implemented)
937     {
938       necr = GET_NECR ();
939       if (GET_NECR_VALID (necr) && GET_NECR_ELOS (necr) && NE_flag)
940         {
941           /* Clear the appropriate NESR and NEEAR registers.  */
942           clear_nesr_neear (current_cpu, target_index, is_float);
943           frv_queue_program_interrupt (current_cpu, FRV_COMMIT_EXCEPTION);
944         }
945     }
946 }
947
948 /* Generate the appropriate fp_exception(s) based on the given status code.  */
949 void
950 frvbf_fpu_error (CGEN_FPU* fpu, int status)
951 {
952   struct frv_fp_exception_info fp_info = {
953     FSR_NO_EXCEPTION, FTT_IEEE_754_EXCEPTION
954   };
955
956   if (status &
957       (sim_fpu_status_invalid_snan |
958        sim_fpu_status_invalid_qnan |
959        sim_fpu_status_invalid_isi |
960        sim_fpu_status_invalid_idi |
961        sim_fpu_status_invalid_zdz |
962        sim_fpu_status_invalid_imz |
963        sim_fpu_status_invalid_cvi |
964        sim_fpu_status_invalid_cmp |
965        sim_fpu_status_invalid_sqrt))
966     fp_info.fsr_mask |= FSR_INVALID_OPERATION;
967
968   if (status & sim_fpu_status_invalid_div0)
969     fp_info.fsr_mask |= FSR_DIVISION_BY_ZERO;
970
971   if (status & sim_fpu_status_inexact)
972     fp_info.fsr_mask |= FSR_INEXACT;
973
974   if (status & sim_fpu_status_overflow)
975     fp_info.fsr_mask |= FSR_OVERFLOW;
976
977   if (status & sim_fpu_status_underflow)
978     fp_info.fsr_mask |= FSR_UNDERFLOW;
979
980   if (status & sim_fpu_status_denorm)
981     {
982       fp_info.fsr_mask |= FSR_DENORMAL_INPUT;
983       fp_info.ftt = FTT_DENORMAL_INPUT;
984     }
985
986   if (fp_info.fsr_mask != FSR_NO_EXCEPTION)
987     {
988       SIM_CPU *current_cpu = (SIM_CPU *)fpu->owner;
989       frv_queue_fp_exception_interrupt (current_cpu, & fp_info);
990     }
991 }
This page took 0.07415 seconds and 4 git commands to generate.