/* Fujitsu FRV opcode support, for GNU Binutils. -*- C -*-
- Copyright 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright 2000, 2001, 2003, 2004, 2005, 2007, 2009
+ Free Software Foundation, Inc.
Contributed by Red Hat Inc; developed under contract from Fujitsu.
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 of the License, or
+ 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,
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
+
/* This file is an addendum to frv.cpu. Heavy use of C code isn't
appropriate in .cpu files, so it resides here. This especially applies
to assembly/disassembly where parsing/printing can be quite involved.
#define FRV_VLIW_SIZE 8 /* fr550 has largest vliw size of 8. */
#define PAD_VLIW_COMBO ,UNIT_NIL,UNIT_NIL,UNIT_NIL,UNIT_NIL
-typedef CGEN_ATTR_VALUE_TYPE VLIW_COMBO[FRV_VLIW_SIZE];
+typedef CGEN_ATTR_VALUE_ENUM_TYPE VLIW_COMBO[FRV_VLIW_SIZE];
typedef struct
{
int constraint_violation;
unsigned long mach;
unsigned long elf_flags;
- CGEN_ATTR_VALUE_TYPE * unit_mapping;
+ CGEN_ATTR_VALUE_ENUM_TYPE * unit_mapping;
VLIW_COMBO * current_vliw;
- CGEN_ATTR_VALUE_TYPE major[FRV_VLIW_SIZE];
+ CGEN_ATTR_VALUE_ENUM_TYPE major[FRV_VLIW_SIZE];
const CGEN_INSN * insn[FRV_VLIW_SIZE];
} FRV_VLIW;
-int frv_is_branch_major (CGEN_ATTR_VALUE_TYPE, unsigned long);
-int frv_is_float_major (CGEN_ATTR_VALUE_TYPE, unsigned long);
-int frv_is_media_major (CGEN_ATTR_VALUE_TYPE, unsigned long);
+int frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
+int frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
+int frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE, unsigned long);
int frv_is_branch_insn (const CGEN_INSN *);
int frv_is_float_insn (const CGEN_INSN *);
int frv_is_media_insn (const CGEN_INSN *);
#include "elf/frv.h"
#include <stdio.h>
+/* DEBUG appears below as argument of OP macro. */
+#undef DEBUG
+
/* Returns TRUE if {MAJOR,MACH} is a major branch of the FRV
development tree. */
bfd_boolean
-frv_is_branch_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
+frv_is_branch_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
{
switch (mach)
{
/* Returns TRUE if {MAJOR,MACH} supports floating point insns. */
bfd_boolean
-frv_is_float_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
+frv_is_float_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
{
switch (mach)
{
/* Returns TRUE if {MAJOR,MACH} supports media insns. */
bfd_boolean
-frv_is_media_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
+frv_is_media_major (CGEN_ATTR_VALUE_ENUM_TYPE major, unsigned long mach)
{
switch (mach)
{
/* Some insns are assigned specialized implementation units which map to
different actual implementation units on different machines. These
tables perform that mapping. */
-static CGEN_ATTR_VALUE_TYPE fr400_unit_mapping[] =
+static CGEN_ATTR_VALUE_ENUM_TYPE fr400_unit_mapping[] =
{
/* unit in insn actual unit */
/* NIL */ UNIT_NIL,
/* Some insns are assigned specialized implementation units which map to
different actual implementation units on different machines. These
tables perform that mapping. */
-static CGEN_ATTR_VALUE_TYPE fr450_unit_mapping[] =
+static CGEN_ATTR_VALUE_ENUM_TYPE fr450_unit_mapping[] =
{
/* unit in insn actual unit */
/* NIL */ UNIT_NIL,
/* MCLRACC-1*/ UNIT_FM0 /* mclracc,A==1 insn only in FM0 unit. */
};
-static CGEN_ATTR_VALUE_TYPE fr500_unit_mapping[] =
+static CGEN_ATTR_VALUE_ENUM_TYPE fr500_unit_mapping[] =
{
/* unit in insn actual unit */
/* NIL */ UNIT_NIL,
/* MCLRACC-1*/ UNIT_FM01 /* mclracc,A==1 in FM0 or FM1 unit. */
};
-static CGEN_ATTR_VALUE_TYPE fr550_unit_mapping[] =
+static CGEN_ATTR_VALUE_ENUM_TYPE fr550_unit_mapping[] =
{
/* unit in insn actual unit */
/* NIL */ UNIT_NIL,
*_allowed_vliw tables above. */
static bfd_boolean
match_unit (FRV_VLIW *vliw,
- CGEN_ATTR_VALUE_TYPE unit1, CGEN_ATTR_VALUE_TYPE unit2)
+ CGEN_ATTR_VALUE_ENUM_TYPE unit1, CGEN_ATTR_VALUE_ENUM_TYPE unit2)
{
/* Map any specialized implementation units to actual ones. */
unit1 = vliw->unit_mapping[unit1];
If one is found then return it. Otherwise return NULL. */
static VLIW_COMBO *
-add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit)
+add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
{
int next = vliw->next_slot;
VLIW_COMBO *current = vliw->current_vliw;
Returns TRUE if found, FALSE otherwise. */
static bfd_boolean
-find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major)
+find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
{
int i;
types. */
static bfd_boolean
-fr400_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major)
+fr400_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
{
/* In the cpu file, all media insns are represented as being allowed in
both media units. This makes it easier since this is the case for fr500.
}
static bfd_boolean
-fr450_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major)
+fr450_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
{
- CGEN_ATTR_VALUE_TYPE other_major;
+ CGEN_ATTR_VALUE_ENUM_TYPE other_major;
/* Our caller guarantees there's at least one other instruction. */
other_major = CGEN_INSN_ATTR_VALUE (vliw->insn[0], CGEN_INSN_FR450_MAJOR);
}
static bfd_boolean
-find_unit_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit)
+find_unit_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE unit)
{
int i;
static bfd_boolean
find_major_in_slot (FRV_VLIW *vliw,
- CGEN_ATTR_VALUE_TYPE major,
- CGEN_ATTR_VALUE_TYPE slot)
+ CGEN_ATTR_VALUE_ENUM_TYPE major,
+ CGEN_ATTR_VALUE_ENUM_TYPE slot)
{
int i;
static bfd_boolean
fr550_check_insn_major_constraints (FRV_VLIW *vliw,
- CGEN_ATTR_VALUE_TYPE major,
+ CGEN_ATTR_VALUE_ENUM_TYPE major,
const CGEN_INSN *insn)
{
- CGEN_ATTR_VALUE_TYPE unit;
- CGEN_ATTR_VALUE_TYPE slot = (*vliw->current_vliw)[vliw->next_slot];
+ CGEN_ATTR_VALUE_ENUM_TYPE unit;
+ CGEN_ATTR_VALUE_ENUM_TYPE slot = (*vliw->current_vliw)[vliw->next_slot];
switch (slot)
{
case UNIT_I2:
}
static bfd_boolean
-fr500_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major)
+fr500_check_insn_major_constraints (FRV_VLIW *vliw, CGEN_ATTR_VALUE_ENUM_TYPE major)
{
/* TODO: A table might be faster for some of the more complex instances
here. */
static bfd_boolean
check_insn_major_constraints (FRV_VLIW *vliw,
- CGEN_ATTR_VALUE_TYPE major,
+ CGEN_ATTR_VALUE_ENUM_TYPE major,
const CGEN_INSN *insn)
{
switch (vliw->mach)
int
frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
{
- int index;
- CGEN_ATTR_VALUE_TYPE major;
- CGEN_ATTR_VALUE_TYPE unit;
+ int slot_index;
+ CGEN_ATTR_VALUE_ENUM_TYPE major;
+ CGEN_ATTR_VALUE_ENUM_TYPE unit;
VLIW_COMBO *new_vliw;
if (vliw->constraint_violation || CGEN_INSN_INVALID_P (insn))
return 1;
- index = vliw->next_slot;
- if (index >= FRV_VLIW_SIZE)
+ slot_index = vliw->next_slot;
+ if (slot_index >= FRV_VLIW_SIZE)
return 1;
unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
break;
}
- if (index <= 0)
+ if (slot_index <= 0)
{
/* Any insn can be added to slot 0. */
while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
if (new_vliw && check_insn_major_constraints (vliw, major, insn))
{
vliw->current_vliw = new_vliw;
- vliw->major[index] = major;
- vliw->insn[index] = insn;
+ vliw->major[slot_index] = major;
+ vliw->insn[slot_index] = insn;
vliw->next_slot++;
return 0;
}
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
{
- /* If bfd_vma is wider than 32 bits, but we have a sign-
- or zero-extension, truncate it. */
- if (value >= - ((bfd_vma)1 << 31)
- || value <= ((bfd_vma)1 << 31) - (bfd_vma)1)
- value &= (((bfd_vma)1 << 16) << 16) - 1;
+ /* If value is wider than 32 bits then be
+ careful about how we extract bits 16-31. */
+ if (sizeof (value) > 4)
+ value &= (((bfd_vma)1 << 16) << 16) - 1;
+
value >>= 16;
}
*valuep = value;