Add support to GDB for the Renesas rl78 architecture.
[external/binutils.git] / sim / frv / traps.c
index 6ab8a2c..dc5198a 100644 (file)
@@ -1,22 +1,22 @@
 /* frv trap support
-   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1999-2001, 2003, 2007-2012 Free Software Foundation,
+   Inc.
    Contributed by Red Hat.
 
 This file is part of the GNU simulators.
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #define WANT_CPU frvbf
 #define WANT_CPU_FRVBF
@@ -30,6 +30,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "bfd.h"
 #include "libiberty.h"
 
+CGEN_ATTR_VALUE_ENUM_TYPE frv_current_fm_slot;
+
 /* The semantic code invokes this for invalid (unrecognized) instructions.  */
 
 SEM_PC
@@ -48,7 +50,8 @@ frv_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia,
 {
   if (sig == sim_core_unaligned_signal)
     {
-      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400)
+      if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400
+         || STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450)
        frv_queue_data_access_error_interrupt (current_cpu, addr);
       else
        frv_queue_mem_address_not_aligned_interrupt (current_cpu, addr);
@@ -189,7 +192,7 @@ frv_itrap (SIM_CPU *current_cpu, PCADDR pc, USI base, SI offset)
 
            if (bfd_find_nearest_line (STATE_PROG_BFD (sd),
                                       STATE_TEXT_SECTION (sd),
-                                      (struct symbol_cache_entry **) 0,
+                                      (struct bfd_symbol **) 0,
                                       pc - STATE_TEXT_START (sd),
                                       &pc_filename, &pc_function, &pc_linenum)
                && (pc_function || pc_filename))
@@ -276,9 +279,11 @@ frv_itrap (SIM_CPU *current_cpu, PCADDR pc, USI base, SI offset)
 void
 frv_mtrap (SIM_CPU *current_cpu)
 {
+  SIM_DESC sd = CPU_STATE (current_cpu);
+
   /* Check the status of media exceptions in MSR0.  */
   SI msr = GET_MSR (0);
-  if (GET_MSR_AOVF (msr) || GET_MSR_MTT (msr))
+  if (GET_MSR_AOVF (msr) || GET_MSR_MTT (msr) && STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550)
     frv_queue_program_interrupt (current_cpu, FRV_MP_EXCEPTION);
 }
 
@@ -584,11 +589,23 @@ frvbf_media_cr_not_aligned (SIM_CPU *current_cpu)
 {
   SIM_DESC sd = CPU_STATE (current_cpu);
 
-  /* On the fr400 this generates an illegal_instruction interrupt.  */
-  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400)
-    frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
-  else
-    frv_set_mp_exception_registers (current_cpu, MTT_CR_NOT_ALIGNED, 0);
+  /* On some machines this generates an illegal_instruction interrupt.  */
+  switch (STATE_ARCHITECTURE (sd)->mach)
+    {
+      /* Note: there is a discrepancy between V2.2 of the FR400
+        instruction manual and the various FR4xx LSI specs.  The former
+        claims that unaligned registers cause an mp_exception while the
+        latter say it's an illegal_instruction.  The LSI specs appear
+        to be correct since MTT is fixed at 1.  */
+    case bfd_mach_fr400:
+    case bfd_mach_fr450:
+    case bfd_mach_fr550:
+      frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
+      break;
+    default:
+      frv_set_mp_exception_registers (current_cpu, MTT_CR_NOT_ALIGNED, 0);
+      break;
+    }
 }
 
 /* Record state for media exception: media_acc_not_aligned.  */
@@ -597,11 +614,19 @@ frvbf_media_acc_not_aligned (SIM_CPU *current_cpu)
 {
   SIM_DESC sd = CPU_STATE (current_cpu);
 
-  /* On the fr400 this generates an illegal_instruction interrupt.  */
-  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400)
-    frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
-  else
-    frv_set_mp_exception_registers (current_cpu, MTT_ACC_NOT_ALIGNED, 0);
+  /* On some machines this generates an illegal_instruction interrupt.  */
+  switch (STATE_ARCHITECTURE (sd)->mach)
+    {
+      /* See comment in frvbf_cr_not_aligned().  */
+    case bfd_mach_fr400:
+    case bfd_mach_fr450:
+    case bfd_mach_fr550:
+      frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
+      break;
+    default:
+      frv_set_mp_exception_registers (current_cpu, MTT_ACC_NOT_ALIGNED, 0);
+      break;
+    }
 }
 
 /* Record state for media exception: media_register_not_aligned.  */
@@ -610,11 +635,19 @@ frvbf_media_register_not_aligned (SIM_CPU *current_cpu)
 {
   SIM_DESC sd = CPU_STATE (current_cpu);
 
-  /* On the fr400 this generates an illegal_instruction interrupt.  */
-  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400)
-    frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
-  else
-    frv_set_mp_exception_registers (current_cpu, MTT_INVALID_FR, 0);
+  /* On some machines this generates an illegal_instruction interrupt.  */
+  switch (STATE_ARCHITECTURE (sd)->mach)
+    {
+      /* See comment in frvbf_cr_not_aligned().  */
+    case bfd_mach_fr400:
+    case bfd_mach_fr450:
+    case bfd_mach_fr550:
+      frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
+      break;
+    default:
+      frv_set_mp_exception_registers (current_cpu, MTT_INVALID_FR, 0);
+      break;
+    }
 }
 
 /* Record state for media exception: media_overflow.  */
@@ -725,6 +758,50 @@ frvbf_check_recovering_store (
     } /* loop over active neear registers.  */
 }
 
+SI
+frvbf_check_acc_range (SIM_CPU *current_cpu, SI regno)
+{
+  /* Only applicable to fr550 */
+  SIM_DESC sd = CPU_STATE (current_cpu);
+  if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550)
+    return;
+
+  /* On the fr550, media insns in slots 0 and 2 can only access
+     accumulators acc0-acc3. Insns in slots 1 and 3 can only access
+     accumulators acc4-acc7 */
+  switch (frv_current_fm_slot)
+    {
+    case UNIT_FM0:
+    case UNIT_FM2:
+      if (regno <= 3)
+       return 1; /* all is ok */
+      break;
+    case UNIT_FM1:
+    case UNIT_FM3:
+      if (regno >= 4)
+       return 1; /* all is ok */
+      break;
+    }
+  
+  /* The specified accumulator is out of range. Queue an illegal_instruction
+     interrupt.  */
+  frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
+  return 0;
+}
+
+void
+frvbf_check_swap_address (SIM_CPU *current_cpu, SI address)
+{
+  /* Only applicable to fr550 */
+  SIM_DESC sd = CPU_STATE (current_cpu);
+  if (STATE_ARCHITECTURE (sd)->mach != bfd_mach_fr550)
+    return;
+
+  /* Adress must be aligned on a word boundary.  */
+  if (address & 0x3)
+    frv_queue_data_access_exception_interrupt (current_cpu);
+}
+
 static void
 clear_nesr_neear (SIM_CPU *current_cpu, SI target_index, BI is_float)
 {