/* tc-csky.c -- Assembler for C-SKY
- Copyright (C) 1989-2018 Free Software Foundation, Inc.
+ Copyright (C) 1989-2020 Free Software Foundation, Inc.
Created by Lifang Xia (lifang_xia@c-sky.com)
Contributed by C-SKY Microsystems and Mentor Graphics.
#include "subsegs.h"
#include "obstack.h"
#include "libiberty.h"
-#include "struc-symbol.h"
#ifdef OBJ_ELF
#include "elf/csky.h"
struct csky_macro_info *macro;
/* Insn size for check_literal. */
unsigned int isize;
+ unsigned int last_isize;
/* Max size of insn for relax frag_var. */
unsigned int max;
/* Indicates which element is in csky_opcode_info op[] array. */
static struct csky_insn_info csky_insn;
-static struct hash_control *csky_opcodes_hash;
-static struct hash_control *csky_macros_hash;
+static htab_t csky_opcodes_hash;
+static htab_t csky_macros_hash;
static struct csky_macro_info v1_macros_table[] =
{
if (mach_flag != 0)
{
- if ((mach_flag & CSKY_ARCH_MASK) != arch_flag && arch_flag != 0)
+ if (((mach_flag & CSKY_ARCH_MASK) != (arch_flag & CSKY_ARCH_MASK))
+ && arch_flag != 0)
as_warn (_("-mcpu conflict with -march option, using -mcpu"));
- if ((mach_flag & ~CSKY_ARCH_MASK) != flags && flags != 0)
+ if (((mach_flag & ~CSKY_ARCH_MASK) != (flags & ~CSKY_ARCH_MASK))
+ && flags != 0)
as_warn (_("-mcpu conflict with other model parameters, using -mcpu"));
}
else if (arch_flag != 0)
}
/* Establish hash table for opcodes and macros. */
- csky_macros_hash = hash_new ();
- csky_opcodes_hash = hash_new ();
+ csky_macros_hash = str_htab_create ();
+ csky_opcodes_hash = str_htab_create ();
for ( ; opcode->mnemonic != NULL; opcode++)
if ((isa_flag & (opcode->isa_flag16 | opcode->isa_flag32)) != 0)
- hash_insert (csky_opcodes_hash, opcode->mnemonic, (char *)opcode);
+ str_hash_insert (csky_opcodes_hash, opcode->mnemonic, (char *)opcode);
for ( ; macro->name != NULL; macro++)
if ((isa_flag & macro->isa_flag) != 0)
- hash_insert (csky_macros_hash, macro->name, (char *)macro);
+ str_hash_insert (csky_macros_hash, macro->name, (char *)macro);
if (do_nolrw && (isa_flag & CSKYV2_ISA_1E2) != 0)
- hash_insert (csky_macros_hash,
+ str_hash_insert (csky_macros_hash,
v2_lrw_macro_opcode.name,
(char *)&v2_lrw_macro_opcode);
/* Set e_flag to ELF Head. */
abort ();
}
- symbolP = symbol_new (symname, now_seg, value, frag);
+ symbolP = symbol_new (symname, now_seg, frag, value);
symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
}
parse_fexp (char *s, expressionS *e, unsigned char isdouble, uint64_t *dbnum)
{
int length; /* Number of chars in an object. */
- register char const *err = NULL; /* Error from scanning float literal. */
- char temp[8];
+ const char *err = NULL; /* Error from scanning float literal. */
+ unsigned char temp[8];
/* input_line_pointer->1st char of a flonum (we hope!). */
input_line_pointer = s;
input_line_pointer += 2;
if (isdouble)
- err = md_atof ('d', temp, &length);
+ err = md_atof ('d', (char *) temp, &length);
else
- err = md_atof ('f', temp, &length);
+ err = md_atof ('f', (char *) temp, &length);
know (length <= 8);
know (err != NULL || length > 0);
{
uint32_t fnum;
if (target_big_endian)
- fnum = (((temp[0] << 24) & 0xffffffff)
- | ((temp[1] << 16) & 0xffffff)
- | ((temp[2] << 8) & 0xffff)
- | (temp[3] & 0xff));
+ fnum = (((uint32_t) temp[0] << 24)
+ | (temp[1] << 16)
+ | (temp[2] << 8)
+ | temp[3]);
else
- fnum = (((temp[3] << 24) & 0xffffffff)
- | ((temp[2] << 16) & 0xffffff)
- | ((temp[1] << 8) & 0xffff)
- | (temp[0] & 0xff));
- e->X_add_number = fnum; }
+ fnum = (((uint32_t) temp[3] << 24)
+ | (temp[2] << 16)
+ | (temp[1] << 8)
+ | temp[0]);
+ e->X_add_number = fnum;
+ }
else
{
if (target_big_endian)
{
- *dbnum = (((temp[0] << 24) & 0xffffffff)
- | ((temp[1] << 16) & 0xffffff)
- | ((temp[2] << 8) & 0xffff)
- | (temp[3] & 0xff));
+ *dbnum = (((uint32_t) temp[0] << 24)
+ | (temp[1] << 16)
+ | (temp[2] << 8)
+ | temp[3]);
*dbnum <<= 32;
- *dbnum |= (((temp[4] << 24) & 0xffffffff)
- | ((temp[5] << 16) & 0xffffff)
- | ((temp[6] << 8) & 0xffff)
- | (temp[7] & 0xff));
+ *dbnum |= (((uint32_t) temp[4] << 24)
+ | (temp[5] << 16)
+ | (temp[6] << 8)
+ | temp[7]);
}
else
{
- *dbnum = (((temp[7] << 24) & 0xffffffff)
- | ((temp[6] << 16) & 0xffffff)
- | ((temp[5] << 8) & 0xffff)
- | (temp[4] & 0xff));
+ *dbnum = (((uint32_t) temp[7] << 24)
+ | (temp[6] << 16)
+ | (temp[5] << 8)
+ | temp[4]);
*dbnum <<= 32;
- *dbnum |= (((temp[3] << 24) & 0xffffffff)
- | ((temp[2] << 16) & 0xffffff)
- | ((temp[1] << 8) & 0xffff)
- | (temp[0] & 0xff));
+ *dbnum |= (((uint32_t) temp[3] << 24)
+ | (temp[2] << 16)
+ | (temp[1] << 8)
+ | temp[0]);
}
}
return input_line_pointer;
csky_insn.number = csky_count_operands (opcode_end);
/* Find hash by name in csky_macros_hash and csky_opcodes_hash. */
- csky_insn.macro = (struct csky_macro_info *) hash_find (csky_macros_hash,
+ csky_insn.macro = (struct csky_macro_info *) str_hash_find (csky_macros_hash,
macro_name);
- csky_insn.opcode = (struct csky_opcode *) hash_find (csky_opcodes_hash,
+ csky_insn.opcode = (struct csky_opcode *) str_hash_find (csky_opcodes_hash,
name);
if (csky_insn.macro == NULL && csky_insn.opcode == NULL)
{
const char *name = "movi";
csky_insn.opcode = (struct csky_opcode *)
- hash_find (csky_opcodes_hash, name);
+ str_hash_find (csky_opcodes_hash, name);
csky_insn.val[csky_insn.idx - 1] = 1 << val;
}
return TRUE;
case OPRND_TYPE_IMM5b_1_31:
return is_imm_over_range (oper, 1, 31, -1);
case OPRND_TYPE_IMM5b_POWER:
- if (is_imm_over_range (oper, 1, ~(1 << 31), 1 << 31))
+ if (is_imm_over_range (oper, 1, (1u << 31) - 1, 1u << 31))
{
int log;
int val = csky_insn.val[csky_insn.idx - 1];
/* This type for "mgeni" in csky v1 ISA. */
case OPRND_TYPE_IMM5b_7_31_POWER:
- if (is_imm_over_range (oper, 1, ~(1 << 31), 1 << 31))
+ if (is_imm_over_range (oper, 1, (1u << 31) - 1, 1u << 31))
{
int log;
int val = csky_insn.val[csky_insn.idx - 1];
{
const char *name = "movi";
csky_insn.opcode = (struct csky_opcode *)
- hash_find (csky_opcodes_hash, name);
+ str_hash_find (csky_opcodes_hash, name);
as_warn (_("translating mgeni to movi"));
}
else
{
const char *op_movi = "movi";
csky_insn.opcode = (struct csky_opcode *)
- hash_find (csky_opcodes_hash, op_movi);
+ str_hash_find (csky_opcodes_hash, op_movi);
if (csky_insn.opcode == NULL)
return FALSE;
csky_insn.val[csky_insn.idx - 1] = (1 << mask_val) - 1;
{
const char *op_movi = "movi";
csky_insn.opcode = (struct csky_opcode *)
- hash_find (csky_opcodes_hash, op_movi);
+ str_hash_find (csky_opcodes_hash, op_movi);
if (csky_insn.opcode == NULL)
return FALSE;
csky_insn.val[csky_insn.idx - 1] = (1 << (mask_val + 1)) - 1;
check_literals (csky_insn.opcode->transfer, csky_insn.max);
}
+ csky_insn.last_isize = csky_insn.isize;
insn_reloc = BFD_RELOC_NONE;
}
md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
{
offsetT disp;
- char *buf = fragp->fr_fix + fragp->fr_literal;
+ char *buf = fragp->fr_fix + &fragp->fr_literal[0];
gas_assert (fragp->fr_symbol);
if (IS_EXTERNAL_SYM (fragp->fr_symbol, asec))
buf[20] = (disp >> 8) & 0xff;
buf[21] = disp & 0xff;
}
+ buf[22] = 0; /* initialise. */
+ buf[23] = 0;
fragp->fr_fix += C32_LEN_PIC;
} /* end if is_unaligned. */
/* We can handle these relocs. */
switch (fixP->fx_r_type)
{
+ case BFD_RELOC_32_PCREL:
case BFD_RELOC_CKCORE_PCREL32:
+ fixP->fx_r_type = BFD_RELOC_CKCORE_PCREL32;
break;
case BFD_RELOC_VTABLE_INHERIT:
fixP->fx_r_type = BFD_RELOC_CKCORE_GNU_VTINHERIT;
{
arelent *rel;
+ if (fixP->fx_pcrel
+ && fixP->fx_r_type == BFD_RELOC_CKCORE_ADDR32)
+ fixP->fx_r_type = BFD_RELOC_CKCORE_PCREL32;
+
rel = xmalloc (sizeof (arelent));
rel->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
*rel->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
s += nlen;
if (*s != '\0')
{
- csky_show_error (ERROR_BAD_END, 0, NULL, NULL);
+ csky_show_error (ERROR_BAD_END, 0, s, NULL);
return FALSE;
}
if (*reg1 == -1 || *reg2 == -1 || *reg3 == -1)
/* Using jsri instruction. */
const char *name = "jsri";
csky_insn.opcode = (struct csky_opcode *)
- hash_find (csky_opcodes_hash, name);
+ str_hash_find (csky_opcodes_hash, name);
csky_insn.opcode_idx = 0;
csky_insn.isize = 2;
{
const char *name = "addc";
csky_insn.opcode
- = (struct csky_opcode *) hash_find (csky_opcodes_hash, name);
+ = (struct csky_opcode *) str_hash_find (csky_opcodes_hash, name);
csky_insn.opcode_idx = 0;
if (csky_insn.isize == 2)
{
val >>= 16;
}
csky_insn.opcode
- = (struct csky_opcode *) hash_find (csky_opcodes_hash, name);
+ = (struct csky_opcode *) str_hash_find (csky_opcodes_hash, name);
csky_insn.opcode_idx = 0;
csky_insn.val[1] = val;
{
const char *name = "nor";
csky_insn.opcode
- = (struct csky_opcode *) hash_find (csky_opcodes_hash, name);
+ = (struct csky_opcode *) str_hash_find (csky_opcodes_hash, name);
csky_insn.opcode_idx = 0;
if (csky_insn.number == 1)
{
|| (csky_insn.e1.X_op == O_symbol && insn_reloc != BFD_RELOC_NONE))
{
if (csky_insn.e1.X_op_symbol != 0
- && csky_insn.e1.X_op_symbol->sy_value.X_op == O_constant
- && 16 == csky_insn.e1.X_op_symbol->sy_value.X_add_number)
+ && symbol_constant_p (csky_insn.e1.X_op_symbol)
+ && S_GET_SEGMENT (csky_insn.e1.X_op_symbol) == absolute_section
+ && 16 == S_GET_VALUE (csky_insn.e1.X_op_symbol))
{
csky_insn.e1.X_op = O_symbol;
if (insn_reloc == BFD_RELOC_CKCORE_GOT32)
}
else if (csky_insn.e1.X_op == O_bit_and)
{
- if (csky_insn.e1.X_op_symbol->sy_value.X_op == O_constant
- && 0xffff == csky_insn.e1.X_op_symbol->sy_value.X_add_number)
+ if (symbol_constant_p (csky_insn.e1.X_op_symbol)
+ && S_GET_SEGMENT (csky_insn.e1.X_op_symbol) == absolute_section
+ && 0xffff == S_GET_VALUE (csky_insn.e1.X_op_symbol))
{
csky_insn.e1.X_op = O_symbol;
if (insn_reloc == BFD_RELOC_CKCORE_GOT32)
csky_insn.inst = csky_insn.opcode->op32[0].opcode | (reg << 16);
csky_insn.isize = 4;
- if (csky_insn.e1.X_op == O_symbol
+ if (csky_insn.number == 3
+ && csky_insn.e1.X_op == O_symbol
&& csky_insn.e2.X_op == O_symbol)
{
fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
4, &csky_insn.e2, 1,
BFD_RELOC_CKCORE_PCREL_BLOOP_IMM4BY4);
}
+ else if (csky_insn.number == 2
+ && csky_insn.e1.X_op == O_symbol)
+ {
+ fix_new_exp (frag_now, csky_insn.output-frag_now->fr_literal,
+ 4, &csky_insn.e1, 1,
+ BFD_RELOC_CKCORE_PCREL_BLOOP_IMM12BY4);
+ if (csky_insn.last_isize == 2)
+ csky_insn.inst |= (0xf << 12);
+ else if (csky_insn.last_isize != 0)
+ csky_insn.inst |= (0xe << 12);
+ else
+ {
+ void *arg = (void *)"bloop can not be the first instruction"\
+ "when the end label is not specified.\n";
+ csky_show_error (ERROR_UNDEFINE, 0, arg, NULL);
+ }
+ }
csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
return TRUE;