/* tc-cr16.c -- Assembler code for the CR16 CPU core.
- Copyright 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007-2016 Free Software Foundation, Inc.
Contributed by M R Swami Reddy <MR.Swami.Reddy@nsc.com>
return;
}
- value |= ((~(-1 << width) & exp.X_add_number)
+ value |= ((~(-(1 << width)) & exp.X_add_number)
<< ((BITS_PER_CHAR * nbytes) - bits_available));
if ((bits_available -= width) == 0
static reg
get_register (char *reg_name)
{
- const reg_entry *reg;
+ const reg_entry *rreg;
- reg = (const reg_entry *) hash_find (reg_hash, reg_name);
+ rreg = (const reg_entry *) hash_find (reg_hash, reg_name);
- if (reg != NULL)
- return reg->value.reg_val;
+ if (rreg != NULL)
+ return rreg->value.reg_val;
return nullregister;
}
static reg
get_register_pair (char *reg_name)
{
- const reg_entry *reg;
+ const reg_entry *rreg;
char tmp_rp[16]="\0";
/* Add '(' and ')' to the reg pair, if its not present. */
- if (reg_name[0] != '(')
+ if (reg_name[0] != '(')
{
tmp_rp[0] = '(';
strcat (tmp_rp, reg_name);
strcat (tmp_rp,")");
- reg = (const reg_entry *) hash_find (regp_hash, tmp_rp);
+ rreg = (const reg_entry *) hash_find (regp_hash, tmp_rp);
}
else
- reg = (const reg_entry *) hash_find (regp_hash, reg_name);
+ rreg = (const reg_entry *) hash_find (regp_hash, reg_name);
- if (reg != NULL)
- return reg->value.reg_val;
+ if (rreg != NULL)
+ return rreg->value.reg_val;
return nullregister;
-}
+}
/* Get the index register 'reg_name'. */
static reg
get_index_register (char *reg_name)
{
- const reg_entry *reg;
+ const reg_entry *rreg;
- reg = (const reg_entry *) hash_find (reg_hash, reg_name);
+ rreg = (const reg_entry *) hash_find (reg_hash, reg_name);
- if ((reg != NULL)
- && ((reg->value.reg_val == 12) || (reg->value.reg_val == 13)))
- return reg->value.reg_val;
+ if ((rreg != NULL)
+ && ((rreg->value.reg_val == 12) || (rreg->value.reg_val == 13)))
+ return rreg->value.reg_val;
return nullregister;
}
static reg
get_index_register_pair (char *reg_name)
{
- const reg_entry *reg;
+ const reg_entry *rreg;
- reg = (const reg_entry *) hash_find (regp_hash, reg_name);
+ rreg = (const reg_entry *) hash_find (regp_hash, reg_name);
- if (reg != NULL)
+ if (rreg != NULL)
{
- if ((reg->value.reg_val != 1) || (reg->value.reg_val != 7)
- || (reg->value.reg_val != 9) || (reg->value.reg_val > 10))
- return reg->value.reg_val;
+ if ((rreg->value.reg_val != 1) || (rreg->value.reg_val != 7)
+ || (rreg->value.reg_val != 9) || (rreg->value.reg_val > 10))
+ return rreg->value.reg_val;
- as_bad (_("Unknown register pair - index relative mode: `%d'"), reg->value.reg_val);
+ as_bad (_("Unknown register pair - index relative mode: `%d'"), rreg->value.reg_val);
}
return nullregister;
static preg
get_pregister (char *preg_name)
{
- const reg_entry *preg;
+ const reg_entry *prreg;
- preg = (const reg_entry *) hash_find (preg_hash, preg_name);
+ prreg = (const reg_entry *) hash_find (preg_hash, preg_name);
- if (preg != NULL)
- return preg->value.preg_val;
+ if (prreg != NULL)
+ return prreg->value.preg_val;
return nullpregister;
}
static preg
get_pregisterp (char *preg_name)
{
- const reg_entry *preg;
+ const reg_entry *prreg;
- preg = (const reg_entry *) hash_find (pregp_hash, preg_name);
+ prreg = (const reg_entry *) hash_find (pregp_hash, preg_name);
- if (preg != NULL)
- return preg->value.preg_val;
+ if (prreg != NULL)
+ return prreg->value.preg_val;
return nullpregister;
}
/* Record a fixup for a cons expression. */
void
-cr16_cons_fix_new (fragS *frag, int offset, int len, expressionS *exp)
+cr16_cons_fix_new (fragS *frag, int offset, int len, expressionS *exp,
+ bfd_reloc_code_real_type rtype)
{
- int rtype = BFD_RELOC_UNUSED;
-
switch (len)
{
default: rtype = BFD_RELOC_NONE; break;
tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS * fixP)
{
arelent * reloc;
- bfd_reloc_code_real_type code;
+
+ /* If symbols are local and resolved, then no relocation needed. */
+ if ( ((fixP->fx_addsy)
+ && (S_GET_SEGMENT (fixP->fx_addsy) == absolute_section))
+ || ((fixP->fx_subsy)
+ && (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)))
+ return NULL;
reloc = xmalloc (sizeof (arelent));
reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
&& GOT_symbol
&& fixP->fx_addsy == GOT_symbol)
{
- code = BFD_RELOC_CR16_GOT_REGREL20;
reloc->addend = fixP->fx_offset = reloc->address;
}
else if ((fixP->fx_r_type == BFD_RELOC_CR16_GOTC_REGREL20)
&& GOT_symbol
&& fixP->fx_addsy == GOT_symbol)
{
- code = BFD_RELOC_CR16_GOTC_REGREL20;
reloc->addend = fixP->fx_offset = reloc->address;
}
#endif
md_apply_fix (fixS *fixP, valueT *valP, segT seg)
{
valueT val = * valP;
- char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
- fixP->fx_offset = 0;
-
- switch (fixP->fx_r_type)
- {
- case BFD_RELOC_CR16_NUM8:
- bfd_put_8 (stdoutput, (unsigned char) val, buf);
- break;
- case BFD_RELOC_CR16_NUM16:
- bfd_put_16 (stdoutput, val, buf);
- break;
- case BFD_RELOC_CR16_NUM32:
- bfd_put_32 (stdoutput, val, buf);
- break;
- case BFD_RELOC_CR16_NUM32a:
- bfd_put_32 (stdoutput, val, buf);
- break;
- default:
- /* We shouldn't ever get here because linkrelax is nonzero. */
- abort ();
- break;
- }
-
- fixP->fx_done = 0;
if (fixP->fx_addsy == NULL
&& fixP->fx_pcrel == 0)
fixP->fx_done = 1;
-
- if (fixP->fx_pcrel == 1
+ else if (fixP->fx_pcrel == 1
&& fixP->fx_addsy != NULL
&& S_GET_SEGMENT (fixP->fx_addsy) == seg)
fixP->fx_done = 1;
+ else
+ fixP->fx_done = 0;
+
+ if (fixP->fx_addsy != NULL && !fixP->fx_pcrel)
+ {
+ val = fixP->fx_offset;
+ fixP->fx_done = 1;
+ }
+
+ if (fixP->fx_done)
+ {
+ char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
+
+ fixP->fx_offset = 0;
+
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_CR16_NUM8:
+ bfd_put_8 (stdoutput, (unsigned char) val, buf);
+ break;
+ case BFD_RELOC_CR16_NUM16:
+ bfd_put_16 (stdoutput, val, buf);
+ break;
+ case BFD_RELOC_CR16_NUM32:
+ bfd_put_32 (stdoutput, val, buf);
+ break;
+ case BFD_RELOC_CR16_NUM32a:
+ bfd_put_32 (stdoutput, val, buf);
+ break;
+ default:
+ /* We shouldn't ever get here because linkrelax is nonzero. */
+ abort ();
+ break;
+ }
+ fixP->fx_done = 0;
+ }
+ else
+ fixP->fx_offset = * valP;
}
/* The location from which a PC relative jump should be calculated,
const reg_entry * register_table,
const unsigned int num_entries)
{
- const reg_entry * reg;
+ const reg_entry * rreg;
const char *hashret;
if ((* hash_table = hash_new ()) == NULL)
as_fatal (_("Virtual memory exhausted"));
- for (reg = register_table;
- reg < (register_table + num_entries);
- reg++)
+ for (rreg = register_table;
+ rreg < (register_table + num_entries);
+ rreg++)
{
- hashret = hash_insert (* hash_table, reg->name, (char *) reg);
+ hashret = hash_insert (* hash_table, rreg->name, (char *) rreg);
if (hashret)
as_fatal (_("Internal Error: Can't hash %s: %s"),
- reg->name, hashret);
+ rreg->name, hashret);
}
}
else if (strneq (input_line_pointer, "@GOT", 4)
|| strneq (input_line_pointer, "@got", 4))
{
- if ((strneq (input_line_pointer, "+", 1))
+ if ((strneq (input_line_pointer, "+", 1))
|| (strneq (input_line_pointer, "-", 1)))
as_warn (_("GOT bad expression with %s."), input_line_pointer);
static int
getreg_image (reg r)
{
- const reg_entry *reg;
+ const reg_entry *rreg;
char *reg_name;
int is_procreg = 0; /* Nonzero means argument should be processor reg. */
/* Check whether the register is in registers table. */
if (r < MAX_REG)
- reg = cr16_regtab + r;
+ rreg = cr16_regtab + r;
else /* Register not found. */
{
as_bad (_("Unknown register: `%d'"), r);
return 0;
}
- reg_name = reg->name;
+ reg_name = rreg->name;
/* Issue a error message when register is illegal. */
#define IMAGE_ERR \
reg_name, ins_parse); \
break;
- switch (reg->type)
+ switch (rreg->type)
{
case CR16_R_REGTYPE:
if (! is_procreg)
- return reg->image;
+ return rreg->image;
else
IMAGE_ERR;
case CR16_P_REGTYPE:
- return reg->image;
+ return rreg->image;
break;
default:
/* Cinv instruction requires special handling. */
-static int
+static void
check_cinv_options (char * operand)
{
char *p = operand;
- int i_used = 0, u_used = 0, d_used = 0;
while (*++p != ']')
{
- if (*p == ',' || *p == ' ')
- continue;
-
- else if (*p == 'i')
- i_used = 1;
- else if (*p == 'u')
- u_used = 1;
- else if (*p == 'd')
- d_used = 1;
- else
- as_bad (_("Illegal `cinv' parameter: `%c'"), *p);
+ switch (*p)
+ {
+ case ',':
+ case ' ':
+ case 'i':
+ case 'u':
+ case 'd':
+ break;
+ default:
+ as_bad (_("Illegal `cinv' parameter: `%c'"), *p);
+ }
}
-
- return 0;
}
/* Retrieve the opcode image of a given register pair.
static int
getregp_image (reg r)
{
- const reg_entry *reg;
+ const reg_entry *rreg;
char *reg_name;
/* Check whether the register is in registers table. */
if (r < MAX_REG)
- reg = cr16_regptab + r;
+ rreg = cr16_regptab + r;
/* Register not found. */
else
{
return 0;
}
- reg_name = reg->name;
+ reg_name = rreg->name;
/* Issue a error message when register pair is illegal. */
#define RPAIR_IMAGE_ERR \
reg_name, ins_parse); \
break;
- switch (reg->type)
+ switch (rreg->type)
{
case CR16_RP_REGTYPE:
- return reg->image;
+ return rreg->image;
default:
RPAIR_IMAGE_ERR;
}
static int
getidxregp_image (reg r)
{
- const reg_entry *reg;
+ const reg_entry *rreg;
char *reg_name;
/* Check whether the register is in registers table. */
if (r < MAX_REG)
- reg = cr16_regptab + r;
+ rreg = cr16_regptab + r;
/* Register not found. */
else
{
return 0;
}
- reg_name = reg->name;
+ reg_name = rreg->name;
/* Issue a error message when register pair is illegal. */
#define IDX_RPAIR_IMAGE_ERR \
as_bad (_("Illegal index register pair (`%s') in Instruction: `%s'"), \
reg_name, ins_parse); \
- if (reg->type == CR16_RP_REGTYPE)
+ if (rreg->type == CR16_RP_REGTYPE)
{
- switch (reg->image)
+ switch (rreg->image)
{
case 0: return 0; break;
case 2: return 1; break;
If the register is illegal for the current instruction,
issue an error. */
static int
-getprocreg_image (reg r)
+getprocreg_image (int r)
{
- const reg_entry *reg;
+ const reg_entry *rreg;
char *reg_name;
/* Check whether the register is in registers table. */
- if (r < MAX_PREG)
- reg = &cr16_pregtab[r - MAX_REG];
+ if (r >= MAX_REG && r < MAX_PREG)
+ rreg = &cr16_pregtab[r - MAX_REG];
/* Register not found. */
else
{
return 0;
}
- reg_name = reg->name;
+ reg_name = rreg->name;
/* Issue a error message when register pair is illegal. */
#define PROCREG_IMAGE_ERR \
reg_name, ins_parse); \
break;
- switch (reg->type)
+ switch (rreg->type)
{
case CR16_P_REGTYPE:
- return reg->image;
+ return rreg->image;
default:
PROCREG_IMAGE_ERR;
}
If the register is illegal for the current instruction,
issue an error. */
static int
-getprocregp_image (reg r)
+getprocregp_image (int r)
{
- const reg_entry *reg;
+ const reg_entry *rreg;
char *reg_name;
int pregptab_disp = 0;
/* Check whether the register is in registers table. */
- if (r < MAX_PREG)
+ if (r >= MAX_REG && r < MAX_PREG)
{
r = r - MAX_REG;
switch (r)
pregptab_disp = 5; break;
default: break;
}
- reg = &cr16_pregptab[r - pregptab_disp];
+ rreg = &cr16_pregptab[r - pregptab_disp];
}
/* Register not found. */
else
return 0;
}
- reg_name = reg->name;
+ reg_name = rreg->name;
/* Issue a error message when register pair is illegal. */
#define PROCREGP_IMAGE_ERR \
reg_name, ins_parse); \
break;
- switch (reg->type)
+ switch (rreg->type)
{
case CR16_P_REGTYPE:
- return reg->image;
+ return rreg->image;
default:
PROCREGP_IMAGE_ERR;
}
int size;
reloc_howto = bfd_reloc_type_lookup (stdoutput, insn->rtype);
-
+
if (!reloc_howto)
abort ();
{
ins cr16_ins;
char *param, param1[32];
- char c;
/* Reset global variables for a new instruction. */
reset_vars (op);
/* Strip the mnemonic. */
for (param = op; *param != 0 && !ISSPACE (*param); param++)
;
- c = *param;
*param++ = '\0';
/* bCC instuctions and adjust the mnemonic by adding extra white spaces. */