#define CGEN_VERBOSE_ASSEMBLER_ERRORS
#define CGEN_DIS_HASH_SIZE 8
#define CGEN_DIS_HASH(buf,value) (((* (unsigned char*) (buf)) >> 6) % CGEN_DIS_HASH_SIZE)
#define CGEN_VALIDATE_INSN_SUPPORTED
extern int iq2000_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn);
static const char * parse_mimm PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
static const char * parse_imm PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
static const char * parse_hi16 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
static const char * parse_lo16 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
int
iq2000_cgen_insn_supported (cd, insn)
CGEN_CPU_DESC cd;
const CGEN_INSN *insn;
{
int machs = cd->machs;
return ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH) & machs) != 0);
}
static int iq2000_cgen_isa_register (strp)
const char **strp;
{
int len;
int ch1, ch2;
if (**strp == 'r' || **strp == 'R')
{
len = strlen (*strp);
if (len == 2)
{
ch1 = (*strp)[1];
if ('0' <= ch1 && ch1 <= '9')
return 1;
}
else if (len == 3)
{
ch1 = (*strp)[1];
ch2 = (*strp)[2];
if (('1' <= ch1 && ch1 <= '2') && ('0' <= ch2 && ch2 <= '9'))
return 1;
if ('3' == ch1 && (ch2 == '0' || ch2 == '1'))
return 1;
}
}
if (**strp == '%' && tolower((*strp)[1]) != 'l' && tolower((*strp)[1]) != 'h')
return 1;
return 0;
}
static const char *
parse_mimm (cd, strp, opindex, valuep)
CGEN_CPU_DESC cd;
const char **strp;
int opindex;
long *valuep;
{
const char *errmsg;
long value;
if (iq2000_cgen_isa_register (strp))
errmsg = _("immediate value cannot be register");
else
{
long value;
errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
if (errmsg == NULL)
{
long x = (-value) & 0xFFFF0000;
if (x != 0 && x != 0xFFFF0000)
errmsg = _("immediate value out of range");
else
*valuep = (-value & 0xFFFF);
}
}
return errmsg;
}
static const char *
parse_imm (cd, strp, opindex, valuep)
CGEN_CPU_DESC cd;
const char **strp;
int opindex;
unsigned long *valuep;
{
const char *errmsg;
long value;
if (iq2000_cgen_isa_register (strp))
errmsg = _("immediate value cannot be register");
else
{
long value;
errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
if (errmsg == NULL)
{
long x = value & 0xFFFF0000;
if (x != 0 && x != 0xFFFF0000)
errmsg = _("immediate value out of range");
else
*valuep = (value & 0xFFFF);
}
}
return errmsg;
}
static const char *
parse_jtargq10 (cd, strp, opindex, reloc, type_addr, valuep)
CGEN_CPU_DESC cd;
const char **strp;
int opindex;
int reloc;
enum cgen_parse_operand_result *type_addr;
bfd_vma *valuep;
{
const char *errmsg;
bfd_vma value;
enum cgen_parse_operand_result result_type = CGEN_PARSE_OPERAND_RESULT_NUMBER;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_OFFSET_21,
&result_type, &value);
if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
{
if (value > 0x7fffff)
return _("21-bit offset out of range");
}
*valuep = (value & 0x7FFFFF);
return errmsg;
}
static const char *
parse_hi16 (cd, strp, opindex, valuep)
CGEN_CPU_DESC cd;
const char **strp;
int opindex;
unsigned long *valuep;
{
if (strncasecmp (*strp, "%hi(", 4) == 0)
{
enum cgen_parse_operand_result result_type;
bfd_vma value;
const char *errmsg;
*strp += 4;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
&result_type, &value);
if (**strp != ')')
return _("missing `)'");
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
{
if (value & 0x8000)
value += 0x10000;
value >>= 16;
}
*valuep = value;
return errmsg;
}
if (strncasecmp (*strp, "%uhi(", 5) == 0)
{
enum cgen_parse_operand_result result_type;
bfd_vma value;
const char *errmsg;
*strp += 5;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_UHI16,
&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 parse_imm (cd, strp, opindex, valuep);
}
static const char *
parse_lo16 (cd, strp, opindex, valuep)
CGEN_CPU_DESC cd;
const char **strp;
int opindex;
long *valuep;
{
if (strncasecmp (*strp, "%lo(", 4) == 0)
{
const char *errmsg;
enum cgen_parse_operand_result result_type;
bfd_vma value;
*strp += 4;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_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;
}
return parse_imm (cd, strp, opindex, valuep);
}
static const char *
parse_mlo16 (cd, strp, opindex, valuep)
CGEN_CPU_DESC cd;
const char **strp;
int opindex;
long *valuep;
{
if (strncasecmp (*strp, "%lo(", 4) == 0)
{
const char *errmsg;
enum cgen_parse_operand_result result_type;
bfd_vma value;
*strp += 4;
errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
&result_type, &value);
if (**strp != ')')
return _("missing `)'");
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
value = (-value) & 0xffff;
*valuep = value;
return errmsg;
}
return parse_mimm (cd, strp, opindex, valuep);
}