unsigned int mach_flag = 0;
unsigned int arch_flag = 0;
unsigned int other_flag = 0;
-unsigned int isa_flag = 0;
+BFD_HOST_U_64_BIT isa_flag = 0;
unsigned int dsp_flag = 0;
typedef struct stack_size_entry
{
const char *name;
unsigned int mach_flag;
- unsigned int isa_flag;
+ BFD_HOST_U_64_BIT isa_flag;
};
typedef enum
const char *name;
/* How many operands : if operands == 5, all of 1,2,3,4 are ok. */
long oprnd_num;
- int isa_flag;
+ BFD_HOST_U_64_BIT isa_flag;
/* Do the work. */
void (*handle_func)(void);
};
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. */
{"ck801", CSKY_ARCH_801, bfd_mach_ck801},
{"ck802", CSKY_ARCH_802, bfd_mach_ck802},
{"ck803", CSKY_ARCH_803, bfd_mach_ck803},
-#define CSKY_ARCH_807_BASE CSKY_ARCH_807 | CSKY_ARCH_DSP
-#define CSKY_ARCH_810_BASE CSKY_ARCH_810 | CSKY_ARCH_DSP
- {"ck807", CSKY_ARCH_807_BASE, bfd_mach_ck807},
- {"ck810", CSKY_ARCH_810_BASE, bfd_mach_ck810},
+ {"ck807", CSKY_ARCH_807, bfd_mach_ck807},
+ {"ck810", CSKY_ARCH_810, bfd_mach_ck810},
+ {"ck860", CSKY_ARCH_860, bfd_mach_ck860},
{NULL, 0, 0}
};
+#define CSKY_ARCH_807_BASE CSKY_ARCH_807 | CSKY_ARCH_DSP
+#define CSKY_ARCH_810_BASE CSKY_ARCH_810 | CSKY_ARCH_DSP
+
/* C-SKY cpus table. */
const struct csky_cpu_info csky_cpus[] =
{
/* CK803 series. */
#define CSKY_ISA_803 (CSKY_ISA_802 | CSKYV2_ISA_2E3 | CSKY_ISA_MP)
#define CSKY_ISA_803R1 (CSKY_ISA_803 | CSKYV2_ISA_3E3R1)
+#define CSKY_ISA_803R2 (CSKY_ISA_803 | CSKYV2_ISA_3E3R1 | CSKYV2_ISA_3E3R2)
#define CSKY_ISA_FLOAT_803 (CSKY_ISA_FLOAT_E1 | CSKY_ISA_FLOAT_1E3)
{"ck803", CSKY_ARCH_803, CSKY_ISA_803 },
{"ck803h", CSKY_ARCH_803, CSKY_ISA_803 },
{"ck803eftr1", CSKY_ARCH_803 | CSKY_ARCH_DSP | CSKY_ARCH_FLOAT, CSKY_ISA_803R1 | CSKY_ISA_DSP_ENHANCE | CSKY_ISA_FLOAT_803 | CSKY_ISA_TRUST},
{"ck803ehftr1", CSKY_ARCH_803 | CSKY_ARCH_DSP | CSKY_ARCH_FLOAT, CSKY_ISA_803R1 | CSKY_ISA_DSP_ENHANCE | CSKY_ISA_FLOAT_803 | CSKY_ISA_TRUST},
+ {"ck803r2", CSKY_ARCH_803, CSKY_ISA_803R2},
+ {"ck803hr2", CSKY_ARCH_803, CSKY_ISA_803R2},
+ {"ck803tr2", CSKY_ARCH_803, CSKY_ISA_803R2 | CSKY_ISA_TRUST},
+ {"ck803htr2", CSKY_ARCH_803, CSKY_ISA_803R2 | CSKY_ISA_TRUST},
+ {"ck803fr2", CSKY_ARCH_803 | CSKY_ARCH_FLOAT, CSKY_ISA_803R2 | CSKY_ISA_FLOAT_803},
+ {"ck803fhr2", CSKY_ARCH_803 | CSKY_ARCH_FLOAT, CSKY_ISA_803R2 | CSKY_ISA_FLOAT_803},
+ {"ck803er2", CSKY_ARCH_803 | CSKY_ARCH_DSP, CSKY_ISA_803R2 | CSKY_ISA_DSP_ENHANCE},
+ {"ck803ehr2", CSKY_ARCH_803 | CSKY_ARCH_DSP, CSKY_ISA_803R2 | CSKY_ISA_DSP_ENHANCE},
+ {"ck803etr2", CSKY_ARCH_803 | CSKY_ARCH_DSP, CSKY_ISA_803R2 | CSKY_ISA_DSP_ENHANCE | CSKY_ISA_TRUST},
+ {"ck803ehtr2", CSKY_ARCH_803 | CSKY_ARCH_DSP, CSKY_ISA_803R2 | CSKY_ISA_DSP_ENHANCE | CSKY_ISA_TRUST},
+ {"ck803efr2", CSKY_ARCH_803 | CSKY_ARCH_DSP | CSKY_ARCH_FLOAT, CSKY_ISA_803R2 | CSKY_ISA_DSP_ENHANCE | CSKY_ISA_FLOAT_803},
+ {"ck803efhr2", CSKY_ARCH_803 | CSKY_ARCH_DSP | CSKY_ARCH_FLOAT, CSKY_ISA_803R2 | CSKY_ISA_DSP_ENHANCE | CSKY_ISA_FLOAT_803},
+ {"ck803ftr2", CSKY_ARCH_803 | CSKY_ARCH_FLOAT, CSKY_ISA_803R2 | CSKY_ISA_FLOAT_803 | CSKY_ISA_TRUST},
+ {"ck803eftr2", CSKY_ARCH_803 | CSKY_ARCH_DSP | CSKY_ARCH_FLOAT, CSKY_ISA_803R2 | CSKY_ISA_DSP_ENHANCE | CSKY_ISA_FLOAT_803 | CSKY_ISA_TRUST},
+ {"ck803efhtr2", CSKY_ARCH_803 | CSKY_ARCH_DSP | CSKY_ARCH_FLOAT, CSKY_ISA_803R2 | CSKY_ISA_DSP_ENHANCE | CSKY_ISA_FLOAT_803 | CSKY_ISA_TRUST},
+
{"ck803s", CSKY_ARCH_803, CSKY_ISA_803R1 },
{"ck803se", CSKY_ARCH_803 | CSKY_ARCH_DSP, CSKY_ISA_803R1 | CSKYV2_ISA_DSP},
{"ck803sj", CSKY_ARCH_803 | CSKY_ARCH_JAVA, CSKY_ISA_803R1 | CSKY_ISA_JAVA},
{"ck810ft", CSKY_ARCH_810_BASE | CSKY_ARCH_FLOAT, CSKY_ISA_810 | CSKYV2_ISA_DSP | CSKY_ISA_VDSP | CSKY_ISA_FLOAT_810 | CSKY_ISA_TRUST},
{"ck810ftv", CSKY_ARCH_810_BASE | CSKY_ARCH_FLOAT, CSKY_ISA_810 | CSKYV2_ISA_DSP | CSKY_ISA_VDSP | CSKY_ISA_FLOAT_810 | CSKY_ISA_TRUST},
+ /* CK860 Series. */
+#define CSKY_ISA_860 (CSKY_ISA_810 | CSKYV2_ISA_10E60)
+#define CSKY_ISA_FLOAT_860 (CSKY_ISA_FLOAT_810)
+ {"ck860", CSKY_ARCH_860, CSKY_ISA_860},
+
{NULL, 0, 0}
};
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[] =
{
-mvdsp enable vector DSP instructions\n"));
}
+static void set_csky_attribute (void)
+{
+ if (mach_flag & CSKY_ARCH_DSP)
+ {
+ if (dsp_flag & CSKY_DSP_FLAG_V2)
+ {
+ /* Set DSPV2. */
+ bfd_elf_add_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
+ Tag_CSKY_DSP_VERSION,
+ VAL_CSKY_DSP_VERSION_2);
+ }
+ else if (isa_flag & CSKY_ISA_DSP)
+ {
+ /* Set DSP extension. */
+ bfd_elf_add_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
+ Tag_CSKY_DSP_VERSION,
+ VAL_CSKY_DSP_VERSION_EXTENSION);
+ }
+ /* Set VDSP attribute. */
+ if (isa_flag & CSKY_ISA_VDSP)
+ bfd_elf_add_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
+ Tag_CSKY_VDSP_VERSION,
+ VAL_CSKY_VDSP_VERSION_1);
+
+ else if (isa_flag & CSKY_ISA_VDSP_2)
+ bfd_elf_add_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
+ Tag_CSKY_VDSP_VERSION,
+ VAL_CSKY_VDSP_VERSION_2);
+
+ }
+
+ if (mach_flag & CSKY_ARCH_FLOAT)
+ {
+ unsigned int val = VAL_CSKY_FPU_HARDFP_SINGLE;
+ if (IS_CSKY_ARCH_V1 (mach_flag)) {
+ bfd_elf_add_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
+ Tag_CSKY_FPU_VERSION,
+ VAL_CSKY_FPU_VERSION_1);
+ }
+ else
+ {
+ if (isa_flag & CSKY_ISA_FLOAT_3E4)
+ {
+ bfd_elf_add_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
+ Tag_CSKY_FPU_VERSION,
+ VAL_CSKY_FPU_VERSION_2);
+ val |= VAL_CSKY_FPU_HARDFP_DOUBLE;
+ }
+ else
+ {
+ bfd_elf_add_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
+ Tag_CSKY_FPU_VERSION,
+ VAL_CSKY_FPU_VERSION_2);
+ }
+
+ bfd_elf_add_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
+ Tag_CSKY_FPU_HARDFP,
+ val);
+ bfd_elf_add_obj_attr_string (stdoutput, OBJ_ATTR_PROC,
+ Tag_CSKY_FPU_NUMBER_MODULE,
+ "IEEE 754");
+ }
+ }
+
+
+ bfd_elf_add_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
+ Tag_CSKY_ISA_FLAGS, isa_flag);
+
+ bfd_elf_add_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
+ Tag_CSKY_ISA_EXT_FLAGS, (isa_flag >> 32));
+}
+
/* Target-specific initialization and option handling. */
void
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)
- mach_flag |= arch_flag | flags;
+ {
+ if ((arch_flag & CSKY_ARCH_MASK) == CSKY_ARCH_810
+ || ((arch_flag & CSKY_ARCH_MASK) == CSKY_ARCH_807)) {
+ /* CK807 and CK810 have DSP instruction by default. */
+ mach_flag |= CSKY_ARCH_DSP;
+ }
+ mach_flag |= arch_flag | flags;
+ }
else
{
#ifdef TARGET_WITH_CPU
for (p_arch = csky_archs; p_arch->arch_flag != 0; p_arch++)
if ((mach_flag & CSKY_ARCH_MASK) == (p_arch->arch_flag & CSKY_ARCH_MASK))
{
+ bfd_elf_add_obj_attr_string (stdoutput, OBJ_ATTR_PROC,
+ Tag_CSKY_ARCH_NAME, p_arch->name);
bfd_mach_flag = p_arch->bfd_mach_flag;
break;
}
for (p_cpu = csky_cpus; p_cpu->mach_flag != 0; p_cpu++)
if ((mach_flag & CPU_ARCH_MASK) == p_cpu->mach_flag)
{
+ bfd_elf_add_obj_attr_string (stdoutput, OBJ_ATTR_PROC,
+ Tag_CSKY_CPU_NAME, p_cpu->name);
isa_flag |= p_cpu->isa_flag;
break;
}
{
if (IS_CSKY_ARCH_803 (mach_flag))
{
- /* In 803, dspv1 is conflict with dspv2. We keep dspv2. */
- if ((dsp_flag & CSKY_DSP_FLAG_V1) && (dsp_flag & CSKY_DSP_FLAG_V2))
- as_warn (_("option -mdsp conflicts with -medsp, only enabling -medsp"));
- isa_flag &= ~(CSKY_ISA_MAC_DSP | CSKY_ISA_DSP);
- isa_flag |= CSKY_ISA_DSP_ENHANCE;
+ if ((dsp_flag & CSKY_DSP_FLAG_V1))
+ {
+ isa_flag |= (CSKY_ISA_MAC_DSP | CSKY_ISA_DSP);
+ isa_flag &= ~CSKY_ISA_DSP_ENHANCE;
+ }
+
+ if ((dsp_flag & CSKY_DSP_FLAG_V2))
+ {
+ isa_flag &= ~(CSKY_ISA_MAC_DSP | CSKY_ISA_DSP);
+ isa_flag |= CSKY_ISA_DSP_ENHANCE;
+ }
+
+ if ((dsp_flag & CSKY_DSP_FLAG_V1)
+ && (dsp_flag & CSKY_DSP_FLAG_V2))
+ {
+ /* In 803, dspv1 is conflict with dspv2. We keep dspv2. */
+ as_warn ("option -mdsp conflicts with -medsp, only enabling -medsp");
+ dsp_flag &= ~CSKY_DSP_FLAG_V1;
+ isa_flag &= ~(CSKY_ISA_MAC_DSP | CSKY_ISA_DSP);
+ isa_flag |= CSKY_ISA_DSP_ENHANCE;
+ }
}
else
{
- isa_flag &= ~CSKY_ISA_DSP_ENHANCE;
- as_warn (_("-medsp option is only supported by ck803s, ignoring -medsp"));
+ if (dsp_flag & CSKY_DSP_FLAG_V2)
+ {
+ dsp_flag &= ~CSKY_DSP_FLAG_V2;
+ isa_flag &= ~CSKY_ISA_DSP_ENHANCE;
+ as_warn ("-medsp option is only supported by ck803s, ignoring -medsp");
+ }
}
;
}
else
do_intr_stack = 1;
}
- /* TODO: add isa_flag(SIMP/CACHE/APS). */
+ /* Add isa_flag(SIMP/CACHE/APS). */
isa_flag |= (mach_flag & CSKY_ARCH_MAC) ? CSKY_ISA_MAC : 0;
isa_flag |= (mach_flag & CSKY_ARCH_MP) ? CSKY_ISA_MP : 0;
isa_flag |= (mach_flag & CSKY_ARCH_CP) ? CSKY_ISA_CP : 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, opcode, 0);
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, macro, 0);
if (do_nolrw && (isa_flag & CSKYV2_ISA_1E2) != 0)
- hash_insert (csky_macros_hash,
- v2_lrw_macro_opcode.name,
- (char *)&v2_lrw_macro_opcode);
+ str_hash_insert (csky_macros_hash,
+ v2_lrw_macro_opcode.name, &v2_lrw_macro_opcode, 0);
/* Set e_flag to ELF Head. */
- bfd_set_private_flags (stdoutput, mach_flag);
+ bfd_set_private_flags (stdoutput, mach_flag & ~(0xffff));
/* Set bfd_mach to bfd backend data. */
bfd_set_arch_mach (stdoutput, bfd_arch_csky, bfd_mach_flag);
+
+ set_csky_attribute ();
}
/* The C-SKY assembler emits mapping symbols $t and $d to mark the
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;
}
{
int reg = 0;
char *s = NULL;
- if ((str[0] == 'v' || str[0] == 'f') && (str[1] == 'r'))
+ if ((TOLOWER(str[0]) == 'v' || TOLOWER(str[0]) == 'f')
+ && (TOLOWER(str[1]) == 'r'))
{
/* It is fpu register. */
s = &str[2];
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,
- macro_name);
- csky_insn.opcode = (struct csky_opcode *) hash_find (csky_opcodes_hash,
- name);
+ csky_insn.macro = (struct csky_macro_info *) str_hash_find (csky_macros_hash,
+ macro_name);
+ csky_insn.opcode = (struct csky_opcode *) str_hash_find (csky_opcodes_hash,
+ name);
if (csky_insn.macro == NULL && csky_insn.opcode == NULL)
return FALSE;
{
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;
{
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;
}
struct tls_addend *ta = &(fixP->tc_fix_data);
fixP->fx_offset = (fixP->fx_frag->fr_address + fixP->fx_where
- (ta->frag->fr_address + ta->offset));
+ *valP = fixP->fx_offset;
}
/* Fall through. */
case BFD_RELOC_CKCORE_TLS_LE32:
struct tls_addend *ta = &(fixP->tc_fix_data);
fixP->fx_offset = (fixP->fx_frag->fr_address + fixP->fx_where
- (ta->frag->fr_address + ta->offset));
+ *valP = fixP->fx_offset;
}
/* Fall through. */
case BFD_RELOC_CKCORE_TLS_LE32:
/* 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.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;