/* tc-cr16.c -- Assembler code for the CR16 CPU core.
- Copyright 2007, 2008, 2009 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
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);
return rreg->value.reg_val;
return nullregister;
-}
+}
/* Get the index register 'reg_name'. */
/* 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)
+ if ( ((fixP->fx_addsy)
&& (S_GET_SEGMENT (fixP->fx_addsy) == absolute_section))
- || ((fixP->fx_subsy)
+ || ((fixP->fx_subsy)
&& (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)))
return NULL;
- reloc = xmalloc (sizeof (arelent));
- reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
+ reloc = XNEW (arelent);
+ reloc->sym_ptr_ptr = XNEW (asymbol *);
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
reloc->addend = fixP->fx_offset;
&& 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
GAS does not understand. */
int
-md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
+md_parse_option (int c ATTRIBUTE_UNUSED, const char *arg ATTRIBUTE_UNUSED)
{
return 0;
}
return;
}
-char *
+const char *
md_atof (int type, char *litP, int *sizeP)
{
return ieee_md_atof (type, litP, sizeP, target_big_endian);
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);
/* 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.
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 *rreg;
char *reg_name;
/* Check whether the register is in registers table. */
- if (r < MAX_PREG)
+ if (r >= MAX_REG && r < MAX_PREG)
rreg = &cr16_pregtab[r - MAX_REG];
/* Register not found. */
else
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 *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)
Returns 1 upon success, 0 upon failure. */
static int
-assemble_insn (char *mnemonic, ins *insn)
+assemble_insn (const char *mnemonic, ins *insn)
{
/* Type of each operand in the current template. */
argtype cur_type[MAX_OPERANDS];
int size;
reloc_howto = bfd_reloc_type_lookup (stdoutput, insn->rtype);
-
+
if (!reloc_howto)
abort ();
}
}
+/* Actually assemble an instruction. */
+
+static void
+cr16_assemble (const char *op, char *param)
+{
+ ins cr16_ins;
+
+ /* Find the instruction. */
+ instruction = (const inst *) hash_find (cr16_inst_hash, op);
+ if (instruction == NULL)
+ {
+ as_bad (_("Unknown opcode: `%s'"), op);
+ return;
+ }
+
+ /* Tie dwarf2 debug info to the address at the start of the insn. */
+ dwarf2_emit_insn (0);
+
+ /* Parse the instruction's operands. */
+ parse_insn (&cr16_ins, param);
+
+ /* Assemble the instruction - return upon failure. */
+ if (assemble_insn (op, &cr16_ins) == 0)
+ return;
+
+ /* Print the instruction. */
+ print_insn (&cr16_ins);
+}
+
/* This is the guts of the machine-dependent assembler. OP points to a
machine dependent instruction. This function is supposed to emit
the frags/bytes it assembles to. */
{
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. */
if (is_bcc_insn (op))
{
strcpy (param1, get_b_cc (op));
- op = "b";
strcat (param1,",");
strcat (param1, param);
param = (char *) ¶m1;
+ cr16_assemble ("b", param);
+ return;
}
/* Checking the cinv options and adjust the mnemonic by removing the
&& ((&cr16_ins)->arg[0].constant >= 0))
{
if (streq ("lshb", op))
- op = "ashub";
+ cr16_assemble ("ashub", param);
else if (streq ("lshd", op))
- op = "ashud";
+ cr16_assemble ("ashud", param);
else
- op = "ashuw";
+ cr16_assemble ("ashuw", param);
+ return;
}
}
- /* Find the instruction. */
- instruction = (const inst *) hash_find (cr16_inst_hash, op);
- if (instruction == NULL)
- {
- as_bad (_("Unknown opcode: `%s'"), op);
- return;
- }
-
- /* Tie dwarf2 debug info to the address at the start of the insn. */
- dwarf2_emit_insn (0);
-
- /* Parse the instruction's operands. */
- parse_insn (&cr16_ins, param);
-
- /* Assemble the instruction - return upon failure. */
- if (assemble_insn (op, &cr16_ins) == 0)
- return;
-
- /* Print the instruction. */
- print_insn (&cr16_ins);
+ cr16_assemble (op, param);
}