#undef CGEN_DIS_HASH_SIZE
#define CGEN_DIS_HASH_SIZE 128
#undef CGEN_DIS_HASH
#define CGEN_DIS_HASH(buffer, value) (((value) >> 18) & 127)
#define CGEN_VERBOSE_ASSEMBLER_ERRORS
#define FRV_VLIW_SIZE 8
#define PAD_VLIW_COMBO ,UNIT_NIL,UNIT_NIL,UNIT_NIL,UNIT_NIL
typedef CGEN_ATTR_VALUE_TYPE VLIW_COMBO[FRV_VLIW_SIZE];
typedef struct
{
int next_slot;
int constraint_violation;
unsigned long mach;
unsigned long elf_flags;
CGEN_ATTR_VALUE_TYPE *unit_mapping;
VLIW_COMBO *current_vliw;
CGEN_ATTR_VALUE_TYPE major[FRV_VLIW_SIZE];
const CGEN_INSN* insn[FRV_VLIW_SIZE];
} FRV_VLIW;
int frv_is_branch_major PARAMS ((CGEN_ATTR_VALUE_TYPE, unsigned long));
int frv_is_float_major PARAMS ((CGEN_ATTR_VALUE_TYPE, unsigned long));
int frv_is_media_major PARAMS ((CGEN_ATTR_VALUE_TYPE, unsigned long));
int frv_is_branch_insn PARAMS ((const CGEN_INSN *));
int frv_is_float_insn PARAMS ((const CGEN_INSN *));
int frv_is_media_insn PARAMS ((const CGEN_INSN *));
void frv_vliw_reset PARAMS ((FRV_VLIW *, unsigned long mach, unsigned long elf_flags));
int frv_vliw_add_insn PARAMS ((FRV_VLIW *, const CGEN_INSN *));
int spr_valid PARAMS ((long));
#include "elf/frv.h"
#include <stdio.h>
static int match_unit
PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE, CGEN_ATTR_VALUE_TYPE));
static int match_vliw
PARAMS ((VLIW_COMBO *, VLIW_COMBO *, int));
static VLIW_COMBO * add_next_to_vliw
PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
static int find_major_in_vliw
PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
static int fr400_check_insn_major_constraints
PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
static int fr450_check_insn_major_constraints
PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
static int fr500_check_insn_major_constraints
PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE));
static int fr550_check_insn_major_constraints
PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE, const CGEN_INSN *));
static int check_insn_major_constraints
PARAMS ((FRV_VLIW *, CGEN_ATTR_VALUE_TYPE, const CGEN_INSN *));
int
frv_is_branch_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
{
switch (mach)
{
case bfd_mach_fr400:
if (major >= FR400_MAJOR_B_1 && major <= FR400_MAJOR_B_6)
return 1;
break;
case bfd_mach_fr450:
if (major >= FR450_MAJOR_B_1 && major <= FR450_MAJOR_B_6)
return 1;
break;
default:
if (major >= FR500_MAJOR_B_1 && major <= FR500_MAJOR_B_6)
return 1;
break;
}
return 0;
}
int
frv_is_float_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
{
switch (mach)
{
case bfd_mach_fr400:
case bfd_mach_fr450:
return 0;
default:
if (major >= FR500_MAJOR_F_1 && major <= FR500_MAJOR_F_8)
return 1;
break;
}
return 0;
}
int
frv_is_media_major (CGEN_ATTR_VALUE_TYPE major, unsigned long mach)
{
switch (mach)
{
case bfd_mach_fr400:
if (major >= FR400_MAJOR_M_1 && major <= FR400_MAJOR_M_2)
return 1;
break;
case bfd_mach_fr450:
if (major >= FR450_MAJOR_M_1 && major <= FR450_MAJOR_M_6)
return 1;
break;
default:
if (major >= FR500_MAJOR_M_1 && major <= FR500_MAJOR_M_8)
return 1;
break;
}
return 0;
}
int
frv_is_branch_insn (const CGEN_INSN *insn)
{
if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
bfd_mach_fr400))
return 1;
if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
bfd_mach_fr450))
return 1;
if (frv_is_branch_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
bfd_mach_fr500))
return 1;
return 0;
}
int
frv_is_float_insn (const CGEN_INSN *insn)
{
if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
bfd_mach_fr400))
return 1;
if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
bfd_mach_fr450))
return 1;
if (frv_is_float_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
bfd_mach_fr500))
return 1;
return 0;
}
int
frv_is_media_insn (const CGEN_INSN *insn)
{
if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR),
bfd_mach_fr400))
return 1;
if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR),
bfd_mach_fr450))
return 1;
if (frv_is_media_major (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR),
bfd_mach_fr500))
return 1;
return 0;
}
static VLIW_COMBO fr400_allowed_vliw[] =
{
{ UNIT_I0, UNIT_I1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
{ UNIT_I0, UNIT_FM0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
{ UNIT_I0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
{ UNIT_FM0, UNIT_FM1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
{ UNIT_FM0, UNIT_B0, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
{ UNIT_B0, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
{ UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
{ UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }
};
static VLIW_COMBO fr500_allowed_vliw[] =
{
{ UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1 PAD_VLIW_COMBO },
{ UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0 PAD_VLIW_COMBO },
{ UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0 PAD_VLIW_COMBO },
{ UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
{ UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
{ UNIT_I0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO },
{ UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1 PAD_VLIW_COMBO },
{ UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL PAD_VLIW_COMBO },
{ UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
{ UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO },
{ UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL PAD_VLIW_COMBO }
};
static VLIW_COMBO fr550_allowed_vliw[] =
{
{ UNIT_I0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL },
{ UNIT_I0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL },
{ UNIT_I0, UNIT_I1, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
{ UNIT_I0, UNIT_B0, UNIT_B1 , UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
{ UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_FM3 },
{ UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_I3, UNIT_B0 },
{ UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_FM3, UNIT_B0 },
{ UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_FM2, UNIT_B0, UNIT_B1 },
{ UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1 },
{ UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL },
{ UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 },
{ UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1 },
{ UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL },
{ UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
{ UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_I3, UNIT_B0, UNIT_B1, UNIT_NIL },
{ UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_I2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
{ UNIT_I0, UNIT_FM0, UNIT_I1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
{ UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL },
{ UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
{ UNIT_I0, UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
{ UNIT_I0, UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
{ UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
{ UNIT_C, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
{ UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_FM3, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL },
{ UNIT_FM0, UNIT_FM1, UNIT_FM2, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL },
{ UNIT_FM0, UNIT_FM1, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
{ UNIT_FM0, UNIT_B0, UNIT_B1, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL },
{ UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL, UNIT_NIL }
};
static CGEN_ATTR_VALUE_TYPE fr400_unit_mapping[] =
{
UNIT_NIL,
UNIT_I0,
UNIT_I1,
UNIT_I01,
UNIT_NIL,
UNIT_NIL,
UNIT_I01,
UNIT_FM0,
UNIT_FM1,
UNIT_FM01,
UNIT_NIL,
UNIT_NIL,
UNIT_FM01,
UNIT_FM0,
UNIT_B0,
UNIT_B0,
UNIT_B0,
UNIT_C,
UNIT_I0,
UNIT_I01,
UNIT_I0,
UNIT_I0,
UNIT_I0,
UNIT_C,
UNIT_FM0,
UNIT_FM0,
UNIT_FM0
};
static CGEN_ATTR_VALUE_TYPE fr450_unit_mapping[] =
{
UNIT_NIL,
UNIT_I0,
UNIT_I1,
UNIT_I01,
UNIT_NIL,
UNIT_NIL,
UNIT_I01,
UNIT_FM0,
UNIT_FM1,
UNIT_FM01,
UNIT_NIL,
UNIT_NIL,
UNIT_FM01,
UNIT_FM0,
UNIT_B0,
UNIT_B0,
UNIT_B0,
UNIT_C,
UNIT_I0,
UNIT_I01,
UNIT_I0,
UNIT_I0,
UNIT_I0,
UNIT_I0,
UNIT_FM0,
UNIT_FM01,
UNIT_FM0
};
static CGEN_ATTR_VALUE_TYPE fr500_unit_mapping[] =
{
UNIT_NIL,
UNIT_I0,
UNIT_I1,
UNIT_I01,
UNIT_NIL,
UNIT_NIL,
UNIT_I01,
UNIT_FM0,
UNIT_FM1,
UNIT_FM01,
UNIT_NIL,
UNIT_NIL,
UNIT_FM01,
UNIT_FM0,
UNIT_B0,
UNIT_B1,
UNIT_B01,
UNIT_C,
UNIT_I01,
UNIT_NIL,
UNIT_I01,
UNIT_I0,
UNIT_I01,
UNIT_C,
UNIT_FM0,
UNIT_FM0,
UNIT_FM01
};
static CGEN_ATTR_VALUE_TYPE fr550_unit_mapping[] =
{
UNIT_NIL,
UNIT_I0,
UNIT_I1,
UNIT_I01,
UNIT_I2,
UNIT_I3,
UNIT_IALL,
UNIT_FM0,
UNIT_FM1,
UNIT_FM01,
UNIT_FM2,
UNIT_FM3,
UNIT_FMALL,
UNIT_FM01,
UNIT_B0,
UNIT_B1,
UNIT_B01,
UNIT_C,
UNIT_I01,
UNIT_NIL,
UNIT_I01,
UNIT_I01,
UNIT_IALL,
UNIT_I0,
UNIT_FMALL,
UNIT_FM01,
UNIT_FM01
};
void
frv_vliw_reset (FRV_VLIW *vliw, unsigned long mach, unsigned long elf_flags)
{
vliw->next_slot = 0;
vliw->constraint_violation = 0;
vliw->mach = mach;
vliw->elf_flags = elf_flags;
switch (mach)
{
case bfd_mach_fr400:
vliw->current_vliw = fr400_allowed_vliw;
vliw->unit_mapping = fr400_unit_mapping;
break;
case bfd_mach_fr450:
vliw->current_vliw = fr400_allowed_vliw;
vliw->unit_mapping = fr450_unit_mapping;
break;
case bfd_mach_fr550:
vliw->current_vliw = fr550_allowed_vliw;
vliw->unit_mapping = fr550_unit_mapping;
break;
default:
vliw->current_vliw = fr500_allowed_vliw;
vliw->unit_mapping = fr500_unit_mapping;
break;
}
}
static int
match_unit (FRV_VLIW *vliw,
CGEN_ATTR_VALUE_TYPE unit1, CGEN_ATTR_VALUE_TYPE unit2)
{
unit1 = vliw->unit_mapping[unit1];
if (unit1 == unit2)
return 1;
if (unit1 < unit2)
return 0;
switch (unit1)
{
case UNIT_I01:
case UNIT_FM01:
case UNIT_B01:
if (unit1 - unit2 <= 2)
return 1;
break;
case UNIT_IALL:
case UNIT_FMALL:
if (unit1 - unit2 <= 5)
return 1;
break;
default:
break;
}
return 0;
}
static int
match_vliw (VLIW_COMBO *vliw1, VLIW_COMBO *vliw2, int vliw_size)
{
int i;
for (i = 0; i < vliw_size; ++i)
{
if ((*vliw1)[i] != (*vliw2)[i])
return 0;
}
return 1;
}
static VLIW_COMBO *
add_next_to_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit)
{
int next = vliw->next_slot;
VLIW_COMBO *current = vliw->current_vliw;
VLIW_COMBO *potential;
if (next <= 0)
{
fprintf (stderr, "frv-opc.c line %d: bad vliw->next_slot value.\n",
__LINE__);
abort ();
}
potential = current;
do
{
if (match_unit (vliw, unit, (*potential)[next]))
return potential;
++potential;
}
while (match_vliw (potential, current, next));
return NULL;
}
static int
find_major_in_vliw (FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major)
{
int i;
for (i = 0; i < vliw->next_slot; ++i)
if (vliw->major[i] == major)
return 1;
return 0;
}
static int
fr400_check_insn_major_constraints (
FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
)
{
switch (major)
{
case FR400_MAJOR_M_2:
return ! find_major_in_vliw (vliw, FR400_MAJOR_M_1)
&& ! find_major_in_vliw (vliw, FR400_MAJOR_M_2);
case FR400_MAJOR_M_1:
return !find_major_in_vliw (vliw, FR400_MAJOR_M_2);
default:
break;
}
return 1;
}
static int
fr450_check_insn_major_constraints (
FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
)
{
CGEN_ATTR_VALUE_TYPE other_major;
other_major = CGEN_INSN_ATTR_VALUE (vliw->insn[0], CGEN_INSN_FR450_MAJOR);
if (other_major == FR450_MAJOR_M_4)
if (major == FR450_MAJOR_M_5 || major == FR450_MAJOR_M_6)
return 1;
switch (major)
{
case FR450_MAJOR_M_2:
case FR450_MAJOR_M_4:
case FR450_MAJOR_M_6:
return !(other_major >= FR450_MAJOR_M_1
&& other_major <= FR450_MAJOR_M_6);
case FR450_MAJOR_M_1:
case FR450_MAJOR_M_3:
case FR450_MAJOR_M_5:
return !(other_major == FR450_MAJOR_M_2
|| other_major == FR450_MAJOR_M_4
|| other_major == FR450_MAJOR_M_6);
default:
return 1;
}
}
static int
find_unit_in_vliw (
FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE unit
)
{
int i;
for (i = 0; i < vliw->next_slot; ++i)
if (CGEN_INSN_ATTR_VALUE (vliw->insn[i], CGEN_INSN_UNIT) == unit)
return 1;
return 0;
}
static int
find_major_in_slot (
FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major, CGEN_ATTR_VALUE_TYPE slot
)
{
int i;
for (i = 0; i < vliw->next_slot; ++i)
if (vliw->major[i] == major && (*vliw->current_vliw)[i] == slot)
return 1;
return 0;
}
static int
fr550_find_media_in_vliw (FRV_VLIW *vliw)
{
int i;
for (i = 0; i < vliw->next_slot; ++i)
{
if (vliw->major[i] < FR550_MAJOR_M_1 || vliw->major[i] > FR550_MAJOR_M_5)
continue;
if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MNOP
|| CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_0
|| CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_MCLRACC_1)
continue;
return 1;
}
return 0;
}
static int
fr550_find_float_in_vliw (FRV_VLIW *vliw)
{
int i;
for (i = 0; i < vliw->next_slot; ++i)
{
if (vliw->major[i] < FR550_MAJOR_F_1 || vliw->major[i] > FR550_MAJOR_F_4)
continue;
if (CGEN_INSN_NUM (vliw->insn[i]) == FRV_INSN_FNOP)
continue;
return 1;
}
return 0;
}
static int
fr550_check_insn_major_constraints (
FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major, const CGEN_INSN *insn
)
{
CGEN_ATTR_VALUE_TYPE unit;
CGEN_ATTR_VALUE_TYPE slot = (*vliw->current_vliw)[vliw->next_slot];
switch (slot)
{
case UNIT_I2:
unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
if (unit == UNIT_STORE)
return find_unit_in_vliw (vliw, UNIT_STORE);
break;
case UNIT_FM2:
case UNIT_FM3:
if (major >= FR550_MAJOR_F_1 && major <= FR550_MAJOR_F_4
&& CGEN_INSN_NUM (insn) != FRV_INSN_FNOP)
return ! fr550_find_media_in_vliw (vliw);
if (major >= FR550_MAJOR_M_1 && major <= FR550_MAJOR_M_5
&& CGEN_INSN_NUM (insn) != FRV_INSN_MNOP)
return ! fr550_find_float_in_vliw (vliw);
if (major == FR550_MAJOR_F_2)
return ! find_major_in_slot (vliw, FR550_MAJOR_F_2, slot - (UNIT_FM2 - UNIT_FM0))
&& ! find_major_in_slot (vliw, FR550_MAJOR_F_4, slot - (UNIT_FM2 - UNIT_FM0));
if (major == FR550_MAJOR_M_2 || major == FR550_MAJOR_M_5)
return ! find_major_in_slot (vliw, FR550_MAJOR_M_2, slot - (UNIT_FM2 - UNIT_FM0));
if (major == FR550_MAJOR_M_4)
return ! find_major_in_slot (vliw, FR550_MAJOR_M_4, slot - (UNIT_FM2 - UNIT_FM0));
break;
default:
break;
}
return 1;
}
static int
fr500_check_insn_major_constraints (
FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major
)
{
switch (major)
{
case FR500_MAJOR_I_1:
case FR500_MAJOR_I_4:
case FR500_MAJOR_I_5:
case FR500_MAJOR_I_6:
case FR500_MAJOR_B_1:
case FR500_MAJOR_B_2:
case FR500_MAJOR_B_3:
case FR500_MAJOR_B_4:
case FR500_MAJOR_B_5:
case FR500_MAJOR_B_6:
case FR500_MAJOR_F_4:
case FR500_MAJOR_F_8:
case FR500_MAJOR_M_8:
return 1;
case FR500_MAJOR_I_2:
return ! find_major_in_vliw (vliw, FR500_MAJOR_I_3);
case FR500_MAJOR_I_3:
return ! find_major_in_vliw (vliw, FR500_MAJOR_I_2);
case FR500_MAJOR_F_1:
case FR500_MAJOR_F_2:
return ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
case FR500_MAJOR_F_3:
return ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
case FR500_MAJOR_F_5:
return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
case FR500_MAJOR_F_6:
return ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
case FR500_MAJOR_F_7:
return ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_F_7)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
case FR500_MAJOR_M_1:
return ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
case FR500_MAJOR_M_2:
case FR500_MAJOR_M_3:
return ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
case FR500_MAJOR_M_4:
return ! find_major_in_vliw (vliw, FR500_MAJOR_M_6);
case FR500_MAJOR_M_5:
return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
case FR500_MAJOR_M_6:
return ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_4)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_7);
case FR500_MAJOR_M_7:
return ! find_major_in_vliw (vliw, FR500_MAJOR_M_1)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_2)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_3)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_5)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_6)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_M_7)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_F_1)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_F_2)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_F_3)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_F_5)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_F_6)
&& ! find_major_in_vliw (vliw, FR500_MAJOR_F_7);
default:
fprintf (stderr, "frv-opc.c, line %d: bad major code, aborting.\n",
__LINE__);
abort ();
break;
}
return 1;
}
static int
check_insn_major_constraints (
FRV_VLIW *vliw, CGEN_ATTR_VALUE_TYPE major, const CGEN_INSN *insn
)
{
int rc;
switch (vliw->mach)
{
case bfd_mach_fr400:
rc = fr400_check_insn_major_constraints (vliw, major);
break;
case bfd_mach_fr450:
rc = fr450_check_insn_major_constraints (vliw, major);
break;
case bfd_mach_fr550:
rc = fr550_check_insn_major_constraints (vliw, major, insn);
break;
default:
rc = fr500_check_insn_major_constraints (vliw, major);
break;
}
return rc;
}
int
frv_vliw_add_insn (FRV_VLIW *vliw, const CGEN_INSN *insn)
{
int index;
CGEN_ATTR_VALUE_TYPE major;
CGEN_ATTR_VALUE_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)
return 1;
unit = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_UNIT);
if (unit == UNIT_NIL)
{
fprintf (stderr, "frv-opc.c line %d: bad insn unit.\n",
__LINE__);
abort ();
}
switch (vliw->mach)
{
case bfd_mach_fr400:
major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR400_MAJOR);
break;
case bfd_mach_fr450:
major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR450_MAJOR);
break;
case bfd_mach_fr550:
major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR550_MAJOR);
break;
default:
major = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_FR500_MAJOR);
break;
}
if (index <= 0)
{
while (! match_unit (vliw, unit, (*vliw->current_vliw)[0]))
++vliw->current_vliw;
vliw->major[0] = major;
vliw->insn[0] = insn;
vliw->next_slot = 1;
return 0;
}
if (! (vliw->elf_flags & EF_FRV_NOPACK))
{
new_vliw = add_next_to_vliw (vliw, unit);
if (new_vliw && check_insn_major_constraints (vliw, major, insn))
{
vliw->current_vliw = new_vliw;
vliw->major[index] = major;
vliw->insn[index] = insn;
vliw->next_slot++;
return 0;
}
if (vliw->mach == bfd_mach_frv)
return 0;
}
vliw->constraint_violation = 1;
return 1;
}
int
spr_valid (regno)
long regno;
{
if (regno < 0) return 0;
if (regno <= 4095) return 1;
return 0;
}
static const char * parse_ulo16
PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
static const char * parse_uslo16
PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
static const char * parse_uhi16
PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
static long parse_register_number
PARAMS ((const char **));
static const char * parse_spr
PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
static const char * parse_d12
PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
static const char * parse_s12
PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
static const char * parse_u12
PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
static const char * parse_even_register
PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *));
static const char * parse_A0
PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
static const char * parse_A1
PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
static const char * parse_A
PARAMS ((CGEN_CPU_DESC, const char **, int, long *, long));
static const char *
parse_ulo16 (cd, strp, opindex, valuep)
CGEN_CPU_DESC cd;
const char **strp;
int opindex;
unsigned long *valuep;
{
const char *errmsg;
enum cgen_parse_operand_result result_type;
bfd_vma value;
if (**strp == '#' || **strp == '%')
{
if (strncasecmp (*strp + 1, "lo(", 3) == 0)
{
*strp += 4;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
&result_type, &value);
if (**strp != ')')
return "missing `)'";
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value &= 0xffff;
*valuep = value;
return errmsg;
}
if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
{
*strp += 9;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
{
*strp += 7;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTLO,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
{
*strp += 15;
errmsg = cgen_parse_address (cd, strp, opindex,
BFD_RELOC_FRV_FUNCDESC_GOTLO,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
{
*strp += 10;
errmsg = cgen_parse_address (cd, strp, opindex,
BFD_RELOC_FRV_GOTOFFLO,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
{
*strp += 18;
errmsg = cgen_parse_address (cd, strp, opindex,
BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value &= 0xffff;
*valuep = value;
return errmsg;
}
}
return cgen_parse_signed_integer (cd, strp, opindex, valuep);
}
static const char *
parse_uslo16 (cd, strp, opindex, valuep)
CGEN_CPU_DESC cd;
const char **strp;
int opindex;
unsigned long *valuep;
{
const char *errmsg;
enum cgen_parse_operand_result result_type;
bfd_vma value;
if (**strp == '#' || **strp == '%')
{
if (strncasecmp (*strp + 1, "lo(", 3) == 0)
{
*strp += 4;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
&result_type, &value);
if (**strp != ')')
return "missing `)'";
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
{
*strp += 9;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
{
*strp += 7;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTLO,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
{
*strp += 15;
errmsg = cgen_parse_address (cd, strp, opindex,
BFD_RELOC_FRV_FUNCDESC_GOTLO,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
{
*strp += 10;
errmsg = cgen_parse_address (cd, strp, opindex,
BFD_RELOC_FRV_GOTOFFLO,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
{
*strp += 18;
errmsg = cgen_parse_address (cd, strp, opindex,
BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value &= 0xffff;
*valuep = value;
return errmsg;
}
}
return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
}
static const char *
parse_uhi16 (cd, strp, opindex, valuep)
CGEN_CPU_DESC cd;
const char **strp;
int opindex;
unsigned long *valuep;
{
const char *errmsg;
enum cgen_parse_operand_result result_type;
bfd_vma value;
if (**strp == '#' || **strp == '%')
{
if (strncasecmp (*strp + 1, "hi(", 3) == 0)
{
*strp += 4;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
&result_type, &value);
if (**strp != ')')
return "missing `)'";
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value >>= 16;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
{
*strp += 9;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELHI,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value >>= 16;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
{
*strp += 7;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTHI,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value >>= 16;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
{
*strp += 15;
errmsg = cgen_parse_address (cd, strp, opindex,
BFD_RELOC_FRV_FUNCDESC_GOTHI,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value >>= 16;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
{
*strp += 10;
errmsg = cgen_parse_address (cd, strp, opindex,
BFD_RELOC_FRV_GOTOFFHI,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value >>= 16;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
{
*strp += 18;
errmsg = cgen_parse_address (cd, strp, opindex,
BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value >>= 16;
*valuep = value;
return errmsg;
}
}
return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
}
static long
parse_register_number (strp)
const char **strp;
{
int regno;
if (**strp < '0' || **strp > '9')
return -1;
regno = **strp - '0';
for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
regno = regno * 10 + (**strp - '0');
return regno;
}
static const char *
parse_spr (cd, strp, table, valuep)
CGEN_CPU_DESC cd;
const char **strp;
CGEN_KEYWORD * table;
long *valuep;
{
const char *save_strp;
long regno;
if (strncasecmp (*strp, "spr[", 4) == 0)
{
*strp += 4;
regno = parse_register_number (strp);
if (**strp != ']')
return "missing `]'";
++*strp;
if (! spr_valid (regno))
return "Special purpose register number is out of range";
*valuep = regno;
return NULL;
}
save_strp = *strp;
regno = parse_register_number (strp);
if (regno != -1)
{
if (! spr_valid (regno))
return "Special purpose register number is out of range";
*valuep = regno;
return NULL;
}
*strp = save_strp;
return cgen_parse_keyword (cd, strp, table, valuep);
}
static const char *
parse_d12 (cd, strp, opindex, valuep)
CGEN_CPU_DESC cd;
const char **strp;
int opindex;
long *valuep;
{
const char *errmsg;
enum cgen_parse_operand_result result_type;
bfd_vma value;
if (**strp == '#' || **strp == '%')
{
if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
{
*strp += 9;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
&result_type, &value);
if (**strp != ')')
return "missing `)'";
++*strp;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
{
*strp += 7;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOT12,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
{
*strp += 15;
errmsg = cgen_parse_address (cd, strp, opindex,
BFD_RELOC_FRV_FUNCDESC_GOT12,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
{
*strp += 10;
errmsg = cgen_parse_address (cd, strp, opindex,
BFD_RELOC_FRV_GOTOFF12,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
{
*strp += 18;
errmsg = cgen_parse_address (cd, strp, opindex,
BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
*valuep = value;
return errmsg;
}
}
return cgen_parse_signed_integer (cd, strp, opindex, valuep);
}
static const char *
parse_s12 (cd, strp, opindex, valuep)
CGEN_CPU_DESC cd;
const char **strp;
int opindex;
long *valuep;
{
const char *errmsg;
enum cgen_parse_operand_result result_type;
bfd_vma value;
if ((**strp == '#' || **strp == '%')
&& strncasecmp (*strp + 1, "gprel12(", 8) == 0)
{
*strp += 9;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
&result_type, &value);
if (**strp != ')')
return "missing `)'";
++*strp;
*valuep = value;
return errmsg;
}
else if ((**strp == '#' || **strp == '%')
&& strncasecmp (*strp + 1, "got12(", 6) == 0)
{
*strp += 7;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOT12,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
*valuep = value;
return errmsg;
}
else if ((**strp == '#' || **strp == '%')
&& strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
{
*strp += 15;
errmsg = cgen_parse_address (cd, strp, opindex,
BFD_RELOC_FRV_FUNCDESC_GOT12,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
*valuep = value;
return errmsg;
}
else if ((**strp == '#' || **strp == '%')
&& strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
{
*strp += 10;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTOFF12,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
*valuep = value;
return errmsg;
}
else if ((**strp == '#' || **strp == '%')
&& strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
{
*strp += 18;
errmsg = cgen_parse_address (cd, strp, opindex,
BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
&result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
*valuep = value;
return errmsg;
}
else
{
if (**strp == '#')
++*strp;
return cgen_parse_signed_integer (cd, strp, opindex, valuep);
}
}
static const char *
parse_u12 (cd, strp, opindex, valuep)
CGEN_CPU_DESC cd;
const char **strp;
int opindex;
long *valuep;
{
const char *errmsg;
enum cgen_parse_operand_result result_type;
bfd_vma value;
if ((**strp == '#' || **strp == '%')
&& strncasecmp (*strp + 1, "gprel12(", 8) == 0)
{
*strp += 9;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELU12,
&result_type, &value);
if (**strp != ')')
return "missing `)'";
++*strp;
*valuep = value;
return errmsg;
}
else
{
if (**strp == '#')
++*strp;
return cgen_parse_signed_integer (cd, strp, opindex, valuep);
}
}
static const char *
parse_A (cd, strp, opindex, valuep, A)
CGEN_CPU_DESC cd;
const char **strp;
int opindex;
long *valuep;
long A;
{
const char *errmsg;
if (**strp == '#')
++*strp;
errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
if (errmsg)
return errmsg;
if (*valuep != A)
return "Value of A operand must be 0 or 1";
return NULL;
}
static const char *
parse_A0 (cd, strp, opindex, valuep)
CGEN_CPU_DESC cd;
const char **strp;
int opindex;
long *valuep;
{
return parse_A (cd, strp, opindex, valuep, 0);
}
static const char *
parse_A1 (cd, strp, opindex, valuep)
CGEN_CPU_DESC cd;
const char **strp;
int opindex;
long *valuep;
{
return parse_A (cd, strp, opindex, valuep, 1);
}
static const char *
parse_even_register (cd, strP, tableP, valueP)
CGEN_CPU_DESC cd;
const char ** strP;
CGEN_KEYWORD * tableP;
long * valueP;
{
const char * errmsg;
const char * saved_star_strP = * strP;
errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
if (errmsg == NULL && ((* valueP) & 1))
{
errmsg = _("register number must be even");
* strP = saved_star_strP;
}
return errmsg;
}
static void print_spr
PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned));
static void print_hi
PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
static void print_lo
PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
static void
print_spr (cd, dis_info, names, regno, attrs)
CGEN_CPU_DESC cd;
PTR dis_info;
CGEN_KEYWORD *names;
long regno;
unsigned int attrs;
{
if (cgen_keyword_lookup_value (names, regno) == NULL)
{
disassemble_info *info = (disassemble_info *) dis_info;
(*info->fprintf_func) (info->stream, "spr[%ld]", regno);
}
else
print_keyword (cd, dis_info, names, regno, attrs);
}
static void
print_hi (cd, dis_info, value, attrs, pc, length)
CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
PTR dis_info;
long value;
unsigned int attrs ATTRIBUTE_UNUSED;
bfd_vma pc ATTRIBUTE_UNUSED;
int length ATTRIBUTE_UNUSED;
{
disassemble_info *info = (disassemble_info *) dis_info;
if (value)
(*info->fprintf_func) (info->stream, "0x%lx", value);
else
(*info->fprintf_func) (info->stream, "hi(0x%lx)", value);
}
static void
print_lo (cd, dis_info, value, attrs, pc, length)
CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
PTR dis_info;
long value;
unsigned int attrs ATTRIBUTE_UNUSED;
bfd_vma pc ATTRIBUTE_UNUSED;
int length ATTRIBUTE_UNUSED;
{
disassemble_info *info = (disassemble_info *) dis_info;
if (value)
(*info->fprintf_func) (info->stream, "0x%lx", value);
else
(*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
}