/* frv trap support
- Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1999-2014 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
#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
{
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);
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))
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);
}
{
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. */
{
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. */
{
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. */
} /* 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)
{