diff options
author | Kuan-Lin Chen <kuanlinchentw@gmail.com> | 2014-09-11 14:25:05 +0800 |
---|---|---|
committer | Kuan-Lin Chen <kuanlinchentw@gmail.com> | 2014-09-16 13:08:00 +0800 |
commit | 1c8f6a4d1fcca9e56ac705a224778bf690122a07 (patch) | |
tree | 7ff41099c5a2f8b433f654b509a7c259899124e4 /gas | |
parent | 40c7a7cb74ee4a9ec0830d734198fcd0e99c3a37 (diff) | |
download | gdb-1c8f6a4d1fcca9e56ac705a224778bf690122a07.zip gdb-1c8f6a4d1fcca9e56ac705a224778bf690122a07.tar.gz gdb-1c8f6a4d1fcca9e56ac705a224778bf690122a07.tar.bz2 |
NDS32: Code refactoring of relaxation.
Refactor each relaxation pattern to raise the maintainability.
In origin, all patterns is analysed in nds32_elf_relax_section,
so it is hard to debug and maintain. Therefore, we classify all
patterns into different functions in this patch.
Moreover, we adjust all optimizations into nds32_elf_relax_section
to take these optimizations in turn. This can promise all relaxation
being done after calling gld${EMULATION_NAME}_after_allocation.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 17 | ||||
-rw-r--r-- | gas/config/tc-nds32.c | 3224 | ||||
-rw-r--r-- | gas/config/tc-nds32.h | 51 |
3 files changed, 2003 insertions, 1289 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 0cbfb40..14a4e52 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,20 @@ +2014-09-16 Kuan-Lin Chen <kuanlinchentw@gmail.com> + + * config/tc-nds32.c (nds32_fsrs, nds32_fdrs, nds32_gprs): Remove. + (relax_table): Add new relaxation pattern. + (do_pseudo_la_internal, do_pseudo_ls_bhw): Expand for PIC suffix. + (do_pseudo_move, do_pseudo_neg, do_pseudo_pushpopm): Fix. + (get_range_type, nds32_elf_record_fixup_exp, nds32_get_align, + nds32_elf_build_relax_relation, md_assemble, invalid_prev_frag, + nds32_relax_frag, md_estimate_size_before_relax): Adjust relaxation. + (relocation_table): Remove. + (relax_ls_table): Load-store relaxation pattern. + (hint_map): Define-use chain pattern. + (nds32_find_reloc_table, nds32_match_hint_insn): Analysis + relaxation pattern. + (nds32_parse_name): Parse PIC suffix. + * config/tc-nds32.h: Declare. + 2014-09-15 H.J. Lu <hongjiu.lu@intel.com> * config/tc-i386.c (OPTION_omit_lock_prefix): Renamed to ... diff --git a/gas/config/tc-nds32.c b/gas/config/tc-nds32.c index 94479ba..353a165 100644 --- a/gas/config/tc-nds32.c +++ b/gas/config/tc-nds32.c @@ -55,23 +55,26 @@ static int enable_16bit = 1; expanded from the pseudo instruction. */ static bfd_boolean pseudo_opcode = FALSE; static struct nds32_relocs_pattern *relocs_list = NULL; +/* Save instruction relation to inserting relaxation relocation. */ struct nds32_relocs_pattern { segT seg; fragS *frag; frchainS *frchain; symbolS *sym; - int reloc; - unsigned int insn; - unsigned int size; + fixS* fixP; + struct nds32_opcode *opcode; char *where; struct nds32_relocs_pattern *next; }; -/* -static int relax_jal_bound = 3; -static int multi_call_relax; -static int pltgot_call_relax; -*/ + +/* Suffix name and relocation. */ +struct suffix_name +{ + char *suffix; + short unsigned int reloc; + int pic; +}; static int vec_size = 0; /* If the assembly code is generated by compiler, it is supposed to have ".flag verbatim" at beginning of the content. We have @@ -79,6 +82,8 @@ static int vec_size = 0; static int verbatim = 0; static struct hash_control *nds32_gprs_hash; static struct hash_control *nds32_hint_hash; +#define TLS_REG "$r27" +#define GOT_NAME "_GLOBAL_OFFSET_TABLE_" /* Generate relocation for relax or not, and the default is true. */ static int enable_relax_relocs = 1; @@ -90,70 +95,13 @@ static int enable_relax_ifc = 0; static int optimize = 0; /* Save option -Os for code size. */ static int optimize_for_space = 0; - -struct nds32_keyword nds32_fsrs[] = -{ - /* Standard names. */ - {"$fs0", 0, 0}, {"$fs1", 1, 0}, {"$fs2", 2, 0}, {"$fs3", 3, 0}, - {"$fs4", 4, 0}, {"$fs5", 5, 0}, {"$fs6", 6, 0}, {"$fs7", 7, 0}, - {"$fs8", 8, 0}, {"$fs9", 9, 0}, {"$fs10", 10, 0}, {"$fs11", 11, 0}, - {"$fs12", 12, 0}, {"$fs13", 13, 0}, {"$fs14", 14, 0}, {"$fs15", 15, 0}, - {"$fs16", 16, 0}, {"$fs17", 17, 0}, {"$fs18", 18, 0}, {"$fs19", 19, 0}, - {"$fs20", 20, 0}, {"$fs21", 21, 0}, {"$fs22", 22, 0}, {"$fs23", 23, 0}, - {"$fs24", 24, 0}, {"$fs25", 25, 0}, {"$fs26", 26, 0}, {"$fs27", 27, 0}, - {"$fs28", 28, 0}, {"$fs29", 29, 0}, {"$fs30", 30, 0}, {"$fs31", 31, 0}, - {NULL, 0, 0} -}; - -struct nds32_keyword nds32_fdrs[] = -{ - /* Standard names. */ - {"$fd0", 0, 0}, {"$fd1", 1, 0}, {"$fd2", 2, 0}, {"$fd3", 3, 0}, - {"$fd4", 4, 0}, {"$fd5", 5, 0}, {"$fd6", 6, 0}, {"$fd7", 7, 0}, - {"$fd8", 8, 0}, {"$fd9", 9, 0}, {"$fd10", 10, 0}, {"$fd11", 11, 0}, - {"$fd12", 12, 0}, {"$fd13", 13, 0}, {"$fd14", 14, 0}, {"$fd15", 15, 0}, - {"$fd16", 16, 0}, {"$fd17", 17, 0}, {"$fd18", 18, 0}, {"$fd19", 19, 0}, - {"$fd20", 20, 0}, {"$fd21", 21, 0}, {"$fd22", 22, 0}, {"$fd23", 23, 0}, - {"$fd24", 24, 0}, {"$fd25", 25, 0}, {"$fd26", 26, 0}, {"$fd27", 27, 0}, - {"$fd28", 28, 0}, {"$fd29", 29, 0}, {"$fd30", 30, 0}, {"$fd31", 31, 0}, - {NULL, 0, 0} -}; - -struct nds32_keyword nds32_gprs[] = -{ - /* Standard names. */ - {"$r0", 0, 0}, {"$r1", 1, 0}, {"$r2", 2, 0}, {"$r3", 3, 0}, - {"$r4", 4, 0}, {"$r5", 5, 0}, {"$r6", 6, 0}, {"$r7", 7, 0}, - {"$r8", 8, 0}, {"$r9", 9, 0}, {"$r10", 10, 0}, {"$r11", 11, 0}, - {"$r12", 12, 0}, {"$r13", 13, 0}, {"$r14", 14, 0}, {"$r15", 15, 0}, - {"$r16", 16, 0}, {"$r17", 17, 0}, {"$r18", 18, 0}, {"$r19", 19, 0}, - {"$r20", 20, 0}, {"$r21", 21, 0}, {"$r22", 22, 0}, {"$r23", 23, 0}, - {"$r24", 24, 0}, {"$r25", 25, 0}, {"$r26", 26, 0}, {"$r27", 27, 0}, - {"$r28", 28, 0}, {"$r29", 29, 0}, {"$r30", 30, 0}, {"$r31", 31, 0}, - /* Names for parameter passing. */ - {"$a0", 0, 0}, {"$a1", 1, 0}, {"$a2", 2, 0}, {"$a3", 3, 0}, - {"$a4", 4, 0}, {"$a5", 5, 0}, - /* Names reserved for 5-bit addressing only. */ - {"$s0", 6, 0}, {"$s1", 7, 0}, {"$s2", 8, 0}, {"$s3", 9, 0}, - {"$s4", 10, 0}, {"$s5", 11, 0}, {"$s6", 12, 0}, {"$s7", 13, 0}, - {"$s8", 14, 0}, {"$s9", 28, 0}, - {"$ta", 15, 0}, - {"$t0", 16, 0}, {"$t1", 17, 0}, {"$t2", 18, 0}, {"$t3", 19, 0}, - {"$t4", 20, 0}, {"$t5", 21, 0}, {"$t6", 22, 0}, {"$t7", 23, 0}, - {"$t8", 24, 0}, {"$t9", 25, 0}, - {"$p0", 26, 0}, {"$p1", 27, 0}, - {"$fp", 28, 0}, {"$gp", 29, 0}, {"$lp", 30, 0}, {"$sp", 31, 0}, - /* Names reserved for 4-bit addressing only. */ - {"$h0", 0, 0}, {"$h1", 1, 0}, {"$h2", 2, 0}, {"$h3", 3, 0}, - {"$h4", 4, 0}, {"$h5", 5, 0}, {"$h6", 6, 0}, {"$h7", 7, 0}, - {"$h8", 8, 0}, {"$h9", 9, 0}, {"$h10", 10, 0}, {"$h11", 11, 0}, - {"$h12", 16, 0}, {"$h13", 17, 0}, {"$h14", 18, 0}, {"$h15", 19, 0}, - /* Names reserved for 3-bit addressing only. */ - {"$o0", 0, 0}, {"$o1", 1, 0}, {"$o2", 2, 0}, {"$o3", 3, 0}, - {"$o4", 4, 0}, {"$o5", 5, 0}, {"$o6", 6, 0}, {"$o7", 7, 0}, - {NULL, 0, 0} -}; - +/* Flag to save label exist. */ +static int label_exist = 0; +/* Flag to save state in omit_fp region. */ +static int in_omit_fp = 0; +extern struct nds32_keyword keyword_gpr[]; +/* Tag there is relax relocation having to link. */ +static bfd_boolean relaxing = FALSE; static struct hash_control *nds32_relax_info_hash; static relax_info_t relax_table[] = @@ -161,7 +109,7 @@ static relax_info_t relax_table[] = { "jal", /* opcode */ BR_RANGE_S16M, /* br_range */ - {{0, 0, 0}}, /* cond_field */ + {{0, 0, 0, FALSE}}, /* cond_field */ { { INSN_JAL /* jal label */ @@ -180,14 +128,14 @@ static relax_info_t relax_table[] = INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JRAL_TA }, /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - {{0, 0, 0}}, /* BR_RANGE_S256 */ - {{0, 0, 0}}, /* BR_RANGE_S16K */ - {{0, 0, 0}}, /* BR_RANGE_S64K */ - {{0, 0, 0}}, /* BR_RANGE_S16M */ - {{0, 0, 0}} /* BR_RANGE_U4G */ - }, /* relax_code_condition */ + }, /* relax_code_seq */ + { + {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ + {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ + {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ + {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ + {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ + }, /* relax_code_condition */ {4, 4, 4, 4, 12}, /* relax_code_size */ {4, 4, 4, 4, 4}, /* relax_branch_isize */ { @@ -209,11 +157,13 @@ static relax_info_t relax_table[] = }, /* BR_RANGE_S16M */ { {0, 4, 0, BFD_RELOC_NDS32_HI20}, - {0, 12, NDS32_RELAX, BFD_RELOC_NDS32_LONGCALL1}, - {4, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_ORIGIN, 0}, - {8, 2, NDS32_CONVERT, 0}, - {0, 0, 0, 0} + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL4}, + {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ }, @@ -221,9 +171,9 @@ static relax_info_t relax_table[] = "bltzal", /* opcode */ BR_RANGE_S64K, /* br_range */ { - {0, 20, 0x1F}, - { 0, 0, 0 } - }, /* cond_field */ + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, /* cond_field */ { { INSN_BLTZAL /* bltzal $rt, label */ @@ -235,38 +185,38 @@ static relax_info_t relax_table[] = INSN_BLTZAL /* bltzal $rt, label */ }, /* BR_RANGE_S64K */ { - INSN_BGEZ, /* bgez $rt, $1 */ + INSN_BGEZ, /* bgez $rt, $1 */ INSN_JAL /* jal label */ }, /* BR_RANGE_S16M */ { - INSN_BGEZ, /* bgez $rt, $1 */ + INSN_BGEZ, /* bgez $rt, $1 */ INSN_SETHI_TA, /* sethi $ta, label */ INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JRAL_TA /* jral $ta */ } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + }, /* relax_code_seq */ { { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S256 */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S64K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16M */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ + }, /* relax_code_condition */ {4, 4, 4, 8, 16}, /* relax_code_size */ {4, 4, 4, 4, 4}, /* relax_branch_isize */ { @@ -283,18 +233,21 @@ static relax_info_t relax_table[] = {0, 0, 0, 0} }, /* BR_RANGE_S64K */ { - {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_17_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGCALL2}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_17_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5}, {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, {0, 0, 0, 0} }, /* BR_RANGE_S16M */ { - {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_17_PCREL}, - {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGCALL3}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_17_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6}, {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_ORIGIN, 0}, - {12, 2, NDS32_CONVERT, 0}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ @@ -303,9 +256,9 @@ static relax_info_t relax_table[] = "bgezal", /* opcode */ BR_RANGE_S64K, /* br_range */ { - {0, 20, 0x1F}, - { 0, 0, 0 } - }, /* cond_field */ + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, /* cond_field */ { { INSN_BGEZAL /* bgezal $rt, label */ @@ -317,38 +270,38 @@ static relax_info_t relax_table[] = INSN_BGEZAL /* bgezal $rt, label */ }, /* BR_RANGE_S64K */ { - INSN_BLTZ, /* bltz $rt, $1 */ + INSN_BLTZ, /* bltz $rt, $1 */ INSN_JAL /* jal label */ }, /* BR_RANGE_S16M */ { - INSN_BLTZ, /* bltz $rt, $1 */ + INSN_BLTZ, /* bltz $rt, $1 */ INSN_SETHI_TA, /* sethi $ta, label */ INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JRAL_TA /* jral $ta */ } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + }, /* relax_code_seq */ { { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S256 */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S64K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16M */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ + }, /* relax_code_condition */ {4, 4, 4, 8, 16}, /* relax_code_size */ {4, 4, 4, 4, 4}, /* relax_branch_isize */ { @@ -365,26 +318,29 @@ static relax_info_t relax_table[] = {0, 0, 0, 0} }, /* BR_RANGE_S64K */ { - {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_17_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGCALL2}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_17_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5}, {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, {0, 0, 0, 0} }, /* BR_RANGE_S16M */ { - {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_17_PCREL}, - {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGCALL3}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_17_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6}, {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_ORIGIN, 0}, - {12, 2, NDS32_CONVERT, 0}, - {0, 0, 0, 0} + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ }, { "j", /* opcode */ BR_RANGE_S16M, /* br_range */ - {{0, 0, 0}}, /* cond_field */ + {{0, 0, 0, FALSE}}, /* cond_field */ { { (INSN_J8 << 16) /* j8 label */ @@ -403,14 +359,14 @@ static relax_info_t relax_table[] = INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JR_TA /* jr $ta */ }, /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - {{0, 0, 0}}, /* BR_RANGE_S256 */ - {{0, 0, 0}}, /* BR_RANGE_S16K */ - {{0, 0, 0}}, /* BR_RANGE_S64K */ - {{0, 0, 0}}, /* BR_RANGE_S16M */ - {{0, 0, 0}} /* BR_RANGE_U4G */ - }, /* relax_code_condition */ + }, /* relax_code_seq */ + { + {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ + {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ + {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ + {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ + {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ + }, /* relax_code_condition */ {2, 4, 4, 4, 12}, /* relax_code_size */ {2, 4, 4, 4, 4}, /* relax_branch_isize */ { @@ -432,18 +388,20 @@ static relax_info_t relax_table[] = }, /* BR_RANGE_S16M */ { {0, 4, 0, BFD_RELOC_NDS32_HI20}, - {0, 12, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP1}, - {4, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_ORIGIN, 0}, - {8, 2, NDS32_CONVERT, 0}, - {0, 0, 0, 0} + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4}, + {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ }, { "j8", /* opcode */ BR_RANGE_S256, /* br_range */ - {{0, 0, 0}}, /* cond_field */ + {{0, 0, 0, FALSE}}, /* cond_field */ { { (INSN_J8 << 16) /* j8 label */ @@ -462,14 +420,14 @@ static relax_info_t relax_table[] = INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JR_TA /* jr $ta */ }, /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - {{0, 0, 0}}, /* BR_RANGE_S256 */ - {{0, 0, 0}}, /* BR_RANGE_S16K */ - {{0, 0, 0}}, /* BR_RANGE_S64K */ - {{0, 0, 0}}, /* BR_RANGE_S16M */ - {{0, 0, 0}} /* BR_RANGE_U4G */ - }, /* relax_code_condition */ + }, /* relax_code_seq */ + { + {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ + {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ + {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ + {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ + {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ + }, /* relax_code_condition */ {2, 4, 4, 4, 12}, /* relax_code_size */ {2, 4, 4, 4, 4}, /* relax_branch_isize */ { @@ -491,11 +449,13 @@ static relax_info_t relax_table[] = }, /* BR_RANGE_S16M */ { {0, 4, 0, BFD_RELOC_NDS32_HI20}, - {0, 12, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP1}, - {4, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {8, 4, NDS32_ORIGIN, 0}, - {8, 2, NDS32_CONVERT, 0}, - {0, 0, 0, 0} + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4}, + {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ }, @@ -503,9 +463,9 @@ static relax_info_t relax_table[] = "beqz", /* opcode */ BR_RANGE_S64K, /* br_range */ { - {0, 20, 0x1F}, - { 0, 0, 0 } - }, /* cond_field */ + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, /* cond_field */ { { INSN_BEQZ /* beqz $rt, label */ @@ -517,44 +477,44 @@ static relax_info_t relax_table[] = INSN_BEQZ /* beqz $rt, label */ }, /* BR_RANGE_S64K */ { - INSN_BNEZ, /* bnez $rt, $1 */ + INSN_BNEZ, /* bnez $rt, $1 */ INSN_J /* j label */ }, /* BR_RANGE_S16M */ { - INSN_BNEZ, /* bnez $rt, $1 */ + INSN_BNEZ, /* bnez $rt, $1 */ INSN_SETHI_TA, /* sethi $ta, label */ INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JR_TA /* jr $ta */ } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + }, /* relax_code_seq */ { { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S256 */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S64K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16M */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ + }, /* relax_code_condition */ {4, 4, 4, 8, 16}, /* relax_code_size */ {4, 4, 4, 4, 4}, /* relax_branch_isize */ { { - {0, 4, 0, BFD_RELOC_NDS32_17_PCREL}, - {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL}, + {0, 4, 0, BFD_RELOC_NDS32_17_PCREL}, + {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} }, /* BR_RANGE_S256 */ { @@ -566,20 +526,24 @@ static relax_info_t relax_table[] = {0, 0, 0, 0} }, /* BR_RANGE_S64K */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2}, - {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, - {0, 0, 0, 0} + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} }, /* BR_RANGE_S16M */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_ORIGIN, 0}, - {12, 2, NDS32_CONVERT, 0}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ @@ -588,9 +552,9 @@ static relax_info_t relax_table[] = "bgez", /* opcode */ BR_RANGE_S64K, /* br_range */ { - {0, 20, 0x1F}, - { 0, 0, 0 } - }, /* cond_field */ + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, /* cond_field */ { { INSN_BGEZ /* bgez $rt, label */ @@ -602,38 +566,38 @@ static relax_info_t relax_table[] = INSN_BGEZ /* bgez $rt, label */ }, /* BR_RANGE_S64K */ { - INSN_BLTZ, /* bltz $rt, $1 */ + INSN_BLTZ, /* bltz $rt, $1 */ INSN_J /* j label */ }, /* BR_RANGE_S16M */ { - INSN_BLTZ, /* bltz $rt, $1 */ + INSN_BLTZ, /* bltz $rt, $1 */ INSN_SETHI_TA, /* sethi $ta, label */ INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JR_TA /* jr $ta */ } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + }, /* relax_code_seq */ { { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S256 */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S64K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16M */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ + }, /* relax_code_condition */ {4, 4, 4, 8, 16}, /* relax_code_size */ {4, 4, 4, 4, 4}, /* relax_branch_isize */ { @@ -650,19 +614,22 @@ static relax_info_t relax_table[] = {0, 0, 0, 0} }, /* BR_RANGE_S64K */ { - {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, {0, 0, 0, 0} }, /* BR_RANGE_S16M */ { - {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_ORIGIN, 0}, - {12, 2, NDS32_CONVERT, 0}, - {0, 0, 0, 0} + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ }, @@ -670,9 +637,9 @@ static relax_info_t relax_table[] = "bnez", /* opcode */ BR_RANGE_S64K, /* br_range */ { - {0, 20, 0x1F}, - { 0, 0, 0 } - }, /* cond_field */ + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, /* cond_field */ { { INSN_BNEZ /* bnez $rt, label */ @@ -684,44 +651,44 @@ static relax_info_t relax_table[] = INSN_BNEZ /* bnez $rt, label */ }, /* BR_RANGE_S64K */ { - INSN_BEQZ, /* beqz $rt, $1 */ + INSN_BEQZ, /* beqz $rt, $1 */ INSN_J /* j label */ }, /* BR_RANGE_S16M */ { - INSN_BEQZ, /* beqz $rt, $1 */ + INSN_BEQZ, /* beqz $rt, $1 */ INSN_SETHI_TA, /* sethi $ta, label */ INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JR_TA /* jr $ta */ } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + }, /* relax_code_seq */ { { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S256 */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S64K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16M */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ + }, /* relax_code_condition */ {4, 4, 4, 8, 16}, /* relax_code_size */ {4, 4, 4, 4, 4}, /* relax_branch_isize */ { { - {0, 4, 0, BFD_RELOC_NDS32_17_PCREL}, - {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL}, + {0, 4, 0, BFD_RELOC_NDS32_17_PCREL}, + {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} }, /* BR_RANGE_S256 */ { @@ -733,21 +700,25 @@ static relax_info_t relax_table[] = {0, 0, 0, 0} }, /* BR_RANGE_S64K */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2}, - {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} }, /* BR_RANGE_S16M */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_ORIGIN, 0}, - {12, 2, NDS32_CONVERT, 0}, - {0, 0, 0, 0} + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ }, @@ -755,9 +726,9 @@ static relax_info_t relax_table[] = "bgtz", /* opcode */ BR_RANGE_S64K, /* br_range */ { - {0, 20, 0x1F}, - { 0, 0, 0 } - }, /* cond_field */ + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, /* cond_field */ { { INSN_BGTZ /* bgtz $rt, label */ @@ -769,38 +740,38 @@ static relax_info_t relax_table[] = INSN_BGTZ /* bgtz $rt, label */ }, /* BR_RANGE_S64K */ { - INSN_BLEZ, /* blez $rt, $1 */ + INSN_BLEZ, /* blez $rt, $1 */ INSN_J /* j label */ }, /* BR_RANGE_S16M */ { - INSN_BLEZ, /* blez $rt, $1 */ + INSN_BLEZ, /* blez $rt, $1 */ INSN_SETHI_TA, /* sethi $ta, label */ INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JR_TA /* jr $ta */ } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + }, /* relax_code_seq */ { { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S256 */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S64K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16M */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ + }, /* relax_code_condition */ {4, 4, 4, 8, 16}, /* relax_code_size */ {4, 4, 4, 4, 4}, /* relax_branch_isize */ { @@ -817,19 +788,22 @@ static relax_info_t relax_table[] = {0, 0, 0, 0} }, /* BR_RANGE_S64K */ { - {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, {0, 0, 0, 0} }, /* BR_RANGE_S16M */ { - {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_ORIGIN, 0}, - {12, 2, NDS32_CONVERT, 0}, - {0, 0, 0, 0} + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ }, @@ -837,9 +811,9 @@ static relax_info_t relax_table[] = "blez", /* opcode */ BR_RANGE_S64K, /* br_range */ { - {0, 20, 0x1F}, - { 0, 0, 0 } - }, /* cond_field */ + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, /* cond_field */ { { INSN_BLEZ /* blez $rt, label */ @@ -851,38 +825,38 @@ static relax_info_t relax_table[] = INSN_BLEZ /* blez $rt, label */ }, /* BR_RANGE_S64K */ { - INSN_BGTZ, /* bgtz $rt, $1 */ + INSN_BGTZ, /* bgtz $rt, $1 */ INSN_J /* j label */ }, /* BR_RANGE_S16M */ { - INSN_BGTZ, /* bgtz $rt, $1 */ + INSN_BGTZ, /* bgtz $rt, $1 */ INSN_SETHI_TA, /* sethi $ta, label */ INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JR_TA /* jr $ta */ } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + }, /* relax_code_seq */ { { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S256 */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S64K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16M */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ + }, /* relax_code_condition */ {4, 4, 4, 8, 16}, /* relax_code_size */ {4, 4, 4, 4, 4}, /* relax_branch_isize */ { @@ -899,19 +873,22 @@ static relax_info_t relax_table[] = {0, 0, 0, 0} }, /* BR_RANGE_S64K */ { - {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, {0, 0, 0, 0} }, /* BR_RANGE_S16M */ { - {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_ORIGIN, 0}, - {12, 2, NDS32_CONVERT, 0}, - {0, 0, 0, 0} + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ }, @@ -919,9 +896,9 @@ static relax_info_t relax_table[] = "bltz", /* opcode */ BR_RANGE_S64K, /* br_range */ { - {0, 20, 0x1F}, - { 0, 0, 0 } - }, /* cond_field */ + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, /* cond_field */ { { INSN_BLTZ /* bltz $rt, label */ @@ -933,38 +910,38 @@ static relax_info_t relax_table[] = INSN_BLTZ /* bltz $rt, label */ }, /* BR_RANGE_S64K */ { - INSN_BGEZ, /* bgez $rt, $1 */ + INSN_BGEZ, /* bgez $rt, $1 */ INSN_J /* j label */ }, /* BR_RANGE_S16M */ { - INSN_BGEZ, /* bgez $rt, $1 */ + INSN_BGEZ, /* bgez $rt, $1 */ INSN_SETHI_TA, /* sethi $ta, label */ INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JR_TA /* jr $ta */ } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + }, /* relax_code_seq */ { { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S256 */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S64K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16M */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ + }, /* relax_code_condition */ {4, 4, 4, 8, 16}, /* relax_code_size */ {4, 4, 4, 4, 4}, /* relax_branch_isize */ { @@ -981,19 +958,22 @@ static relax_info_t relax_table[] = {0, 0, 0, 0} }, /* BR_RANGE_S64K */ { - {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, {0, 0, 0, 0} }, /* BR_RANGE_S16M */ { - {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_ORIGIN, 0}, - {12, 2, NDS32_CONVERT, 0}, - {0, 0, 0, 0} + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ }, @@ -1001,10 +981,10 @@ static relax_info_t relax_table[] = "beq", /* opcode */ BR_RANGE_S16K, /* br_range */ { - {0, 20, 0x1F}, - {0, 15, 0x1F}, - { 0, 0, 0 } - }, /* cond_field */ + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, /* cond_field */ { { INSN_BEQ /* beq $rt, $ra, label */ @@ -1026,40 +1006,40 @@ static relax_info_t relax_table[] = INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JR_TA /* jr $ta */ } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + }, /* relax_code_seq */ { { - {0, 20, 0x1F}, - {0, 15, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S256 */ { - {0, 20, 0x1F}, - {0, 15, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16K */ { - {0, 20, 0x1F}, - {0, 15, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S64K */ { - {0, 20, 0x1F}, - {0, 15, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16M */ { - {0, 20, 0x1F}, - {0, 15, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ + }, /* relax_code_condition */ {4, 4, 8, 8, 16}, /* relax_code_size */ {4, 4, 4, 4, 4}, /* relax_branch_isize */ { { - {0, 4, NDS32_ORIGIN, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL}, + {0, 4, 0, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} }, /* BR_RANGE_S256 */ { @@ -1067,28 +1047,34 @@ static relax_info_t relax_table[] = {0, 0, 0, 0} }, /* BR_RANGE_S16K */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2}, - {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} }, /* BR_RANGE_S64K */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2}, - {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_ABS, BFD_RELOC_NDS32_EMPTY}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} }, /* BR_RANGE_S16M */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_ORIGIN, 0}, - {12, 2, NDS32_CONVERT, 0}, - {0, 0, 0, 0} + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ }, @@ -1096,10 +1082,10 @@ static relax_info_t relax_table[] = "bne", /* opcode */ BR_RANGE_S16K, /* br_range */ { - {0, 20, 0x1F}, - {0, 15, 0x1F}, - { 0, 0, 0 } - }, /* cond_field */ + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, /* cond_field */ { { INSN_BNE /* bne $rt, $ra, label */ @@ -1121,40 +1107,40 @@ static relax_info_t relax_table[] = INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JR_TA /* jr $ta */ } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + }, /* relax_code_seq */ { { - {0, 20, 0x1F}, - {0, 15, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S256 */ { - {0, 20, 0x1F}, - {0, 15, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16K */ { - {0, 20, 0x1F}, - {0, 15, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S64K */ { - {0, 20, 0x1F}, - {0, 15, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16M */ { - {0, 20, 0x1F}, - {0, 15, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 15, 0x1F, FALSE}, + {0, 0, 0, FALSE} } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ + }, /* relax_code_condition */ {4, 4, 8, 8, 16}, /* relax_code_size */ {4, 4, 4, 4, 4}, /* relax_branch_isize */ { { - {0, 4, NDS32_ORIGIN, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL}, + {0, 4, 0, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} }, /* BR_RANGE_S256 */ { @@ -1162,28 +1148,33 @@ static relax_info_t relax_table[] = {0, 0, 0, 0} }, /* BR_RANGE_S16K */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2}, - {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} }, /* BR_RANGE_S64K */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2}, - {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} }, /* BR_RANGE_S16M */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_ORIGIN, 0}, - {12, 2, NDS32_CONVERT, 0}, - {0, 0, 0, 0} + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ }, @@ -1191,12 +1182,12 @@ static relax_info_t relax_table[] = "beqz38", /* opcode */ BR_RANGE_S256, /* br_range */ { - {0, 8, 0x7}, - { 0, 0, 0 } - }, /* cond_field */ + {0, 8, 0x7, FALSE}, + {0, 0, 0, FALSE} + }, /* cond_field */ { { - INSN_BEQZ /* beqz $rt, label */ + INSN_BEQZ38 << 16 /* beqz $rt, label */ }, /* BR_RANGE_S256 */ { INSN_BEQZ /* beqz $rt, label */ @@ -1205,7 +1196,7 @@ static relax_info_t relax_table[] = INSN_BEQZ /* beqz $rt, label */ }, /* BR_RANGE_S64K */ { - INSN_BNEZ, /* bnez $rt, $1 */ + INSN_BNEZ, /* bnez $rt, $1 */ INSN_J /* j label */ }, /* BR_RANGE_S16M */ { @@ -1214,35 +1205,34 @@ static relax_info_t relax_table[] = INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JR_TA /* jr $ta */ } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + }, /* relax_code_seq */ { { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 8, 0x7, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S256 */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S64K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16M */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 4, 4, 8, 16}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ + }, /* relax_code_condition */ + {2, 4, 4, 8, 16}, /* relax_code_size */ + {2, 4, 4, 4, 4}, /* relax_branch_isize */ { { - {0, 4, NDS32_ORIGIN, BFD_RELOC_NDS32_17_PCREL}, - {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL}, + {0, 2, 0, BFD_RELOC_NDS32_9_PCREL}, {0, 0, 0, 0} }, /* BR_RANGE_S256 */ { @@ -1254,21 +1244,25 @@ static relax_info_t relax_table[] = {0, 0, 0, 0} }, /* BR_RANGE_S64K */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2}, - {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} }, /* BR_RANGE_S16M */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_ORIGIN, 0}, - {12, 2, NDS32_CONVERT, 0}, - {0, 0, 0, 0} + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ }, @@ -1276,12 +1270,12 @@ static relax_info_t relax_table[] = "bnez38", /* opcode */ BR_RANGE_S256, /* br_range */ { - {0, 8, 0x7}, - { 0, 0, 0 } - }, /* cond_field */ + {0, 8, 0x7, FALSE}, + {0, 0, 0, FALSE} + }, /* cond_field */ { { - INSN_BNEZ /* bnez $rt, label */ + INSN_BNEZ38 << 16 /* bnez $rt, label */ }, /* BR_RANGE_S256 */ { INSN_BNEZ /* bnez $rt, label */ @@ -1290,7 +1284,7 @@ static relax_info_t relax_table[] = INSN_BNEZ /* bnez $rt, label */ }, /* BR_RANGE_S64K */ { - INSN_BEQZ, /* beqz $rt, $1 */ + INSN_BEQZ, /* beqz $rt, $1 */ INSN_J /* j label */ }, /* BR_RANGE_S16M */ { @@ -1299,35 +1293,34 @@ static relax_info_t relax_table[] = INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JR_TA /* jr $ta */ } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + }, /* relax_code_seq */ { { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 8, 0x7, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S256 */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S64K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16M */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 4, 4, 8, 16}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ + }, /* relax_code_condition */ + {2, 4, 4, 8, 16}, /* relax_code_size */ + {2, 4, 4, 4, 4}, /* relax_branch_isize */ { { - {0, 4, NDS32_ORIGIN, BFD_RELOC_NDS32_17_PCREL}, - {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL}, + {0, 2, 0, BFD_RELOC_NDS32_9_PCREL}, {0, 0, 0, 0} }, /* BR_RANGE_S256 */ { @@ -1339,40 +1332,44 @@ static relax_info_t relax_table[] = {0, 0, 0, 0} }, /* BR_RANGE_S64K */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2}, - {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} }, /* BR_RANGE_S16M */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_ORIGIN, 0}, - {12, 2, NDS32_CONVERT, 0}, - {0, 0, 0, 0} + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ }, { "beqzs8", /* opcode */ BR_RANGE_S256, /* br_range */ - {{0, 0, 0}}, /* cond_field */ + {{0, 0, 0, FALSE}}, /* cond_field */ { { - INSN_BEQZ_TA /* beqz $r15, label */ + INSN_BEQZS8 << 16 /* beqz $r15, label */ }, /* BR_RANGE_S256 */ { - INSN_BNEZ /* bnez $rt, label */ + INSN_BEQZ_TA /* bnez $rt, label */ }, /* BR_RANGE_S16K */ { - INSN_BNEZ /* bnez $rt, label */ + INSN_BEQZ_TA /* bnez $rt, label */ }, /* BR_RANGE_S64K */ { - INSN_BNEZ_TA, /* bnez $r15, $1 */ + INSN_BNEZ_TA, /* bnez $r15, $1 */ INSN_J /* j label */ }, /* BR_RANGE_S16M */ { @@ -1381,20 +1378,19 @@ static relax_info_t relax_table[] = INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JR_TA /* jr $ta */ } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - {{0, 0, 0}}, /* BR_RANGE_S256 */ - {{0, 0, 0}}, /* BR_RANGE_S16K */ - {{0, 0, 0}}, /* BR_RANGE_S64K */ - {{0, 0, 0}}, /* BR_RANGE_S16M */ - {{0, 0, 0}} /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 4, 4, 8, 16}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ + }, /* relax_code_seq */ + { + {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ + {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ + {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ + {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ + {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ + }, /* relax_code_condition */ + {2, 4, 4, 8, 16}, /* relax_code_size */ + {2, 4, 4, 4, 4}, /* relax_branch_isize */ { { - {0, 4, NDS32_ORIGIN, BFD_RELOC_NDS32_17_PCREL}, - {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL}, + {0, 2, 0, BFD_RELOC_NDS32_9_PCREL}, {0, 0, 0, 0} }, /* BR_RANGE_S256 */ { @@ -1406,20 +1402,24 @@ static relax_info_t relax_table[] = {0, 0, 0, 0} }, /* BR_RANGE_S64K */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2}, - {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} }, /* BR_RANGE_S16M */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_ORIGIN, 0}, - {12, 2, NDS32_CONVERT, 0}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ @@ -1427,10 +1427,10 @@ static relax_info_t relax_table[] = { "bnezs8", /* opcode */ BR_RANGE_S256, /* br_range */ - {{0, 0, 0}}, /* cond_field */ + {{0, 0, 0, FALSE}}, /* cond_field */ { { - INSN_BNEZ_TA /* bnez $r15, label */ + INSN_BNEZS8 << 16 /* bnez $r15, label */ }, /* BR_RANGE_S256 */ { INSN_BNEZ_TA /* bnez $r15, label */ @@ -1439,29 +1439,28 @@ static relax_info_t relax_table[] = INSN_BNEZ_TA /* bnez $r15, label */ }, /* BR_RANGE_S64K */ { - INSN_BEQZ_TA, /* beqz $r15, $1 */ + INSN_BEQZ_TA, /* beqz $r15, $1 */ INSN_J /* j label */ }, /* BR_RANGE_S16M */ { - INSN_BEQZ_TA, /* beqz $r15, $1 */ + INSN_BEQZ_TA, /* beqz $r15, $1 */ INSN_SETHI_TA, /* sethi $ta, label */ INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JR_TA /* jr $ta */ } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ - { - {{0, 0, 0}}, /* BR_RANGE_S256 */ - {{0, 0, 0}}, /* BR_RANGE_S16K */ - {{0, 0, 0}}, /* BR_RANGE_S64K */ - {{0, 0, 0}}, /* BR_RANGE_S16M */ - {{0, 0, 0}} /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 4, 4, 8, 16}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ + }, /* relax_code_seq */ + { + {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ + {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ + {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ + {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ + {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ + }, /* relax_code_condition */ + {2, 4, 4, 8, 16}, /* relax_code_size */ + {2, 4, 4, 4, 4}, /* relax_branch_isize */ { { - {0, 4, NDS32_ORIGIN, BFD_RELOC_NDS32_17_PCREL}, - {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL}, + {0, 2, 0, BFD_RELOC_NDS32_9_PCREL}, {0, 0, 0, 0} }, /* BR_RANGE_S256 */ { @@ -1473,21 +1472,25 @@ static relax_info_t relax_table[] = {0, 0, 0, 0} }, /* BR_RANGE_S64K */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2}, - {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} }, /* BR_RANGE_S16M */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_ORIGIN, 0}, - {12, 2, NDS32_CONVERT, 0}, - {0, 0, 0, 0} + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ }, @@ -1495,59 +1498,58 @@ static relax_info_t relax_table[] = "bnes38", /* opcode */ BR_RANGE_S256, /* br_range */ { - {0, 8, 0x7}, - { 0, 0, 0 } - }, /* cond_field */ + {0, 8, 0x7, FALSE}, + {0, 0, 0, FALSE} + }, /* cond_field */ { { - INSN_BNE_R5 /* bne $rt, $r5, label */ + INSN_BNES38 << 16 /* bne $rt, $R5, label */ }, /* BR_RANGE_S256 */ { - INSN_BNE_R5 /* bne $rt, $r5, label */ + INSN_BNE_R5 /* bne $rt, $R5, label */ }, /* BR_RANGE_S16K */ { - INSN_BEQ_R5, /* beq $rt, $r5, $1 */ + INSN_BEQ_R5, /* beq $rt, $R5, $1 */ INSN_J /* j label */ }, /* BR_RANGE_S64K */ { - INSN_BEQ_R5, /* beq $rt, $r5, $1 */ + INSN_BEQ_R5, /* beq $rt, $R5, $1 */ INSN_J /* j label */ }, /* BR_RANGE_S16M */ { - INSN_BEQ_R5, /* beq $rt, $r5, $1 */ + INSN_BEQ_R5, /* beq $rt, $R5, $1 */ INSN_SETHI_TA, /* sethi $ta, label */ INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JR_TA /* jr $ta */ } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + }, /* relax_code_seq */ { { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 8, 0x7, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S256 */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S64K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16M */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 4, 8, 8, 16}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ + }, /* relax_code_condition */ + {2, 4, 8, 8, 16}, /* relax_code_size */ + {2, 4, 4, 4, 4}, /* relax_branch_isize */ { { - {0, 4, NDS32_ORIGIN, BFD_RELOC_NDS32_17_PCREL}, - {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL}, + {0, 2, 0, BFD_RELOC_NDS32_9_PCREL}, {0, 0, 0, 0} }, /* BR_RANGE_S256 */ { @@ -1555,28 +1557,33 @@ static relax_info_t relax_table[] = {0, 0, 0, 0} }, /* BR_RANGE_S16K */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2}, - {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} }, /* BR_RANGE_S64K */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2}, - {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} }, /* BR_RANGE_S16M */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_ORIGIN, 0}, - {12, 2, NDS32_CONVERT, 0}, - {0, 0, 0, 0} + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ }, @@ -1584,59 +1591,58 @@ static relax_info_t relax_table[] = "beqs38", /* opcode */ BR_RANGE_S256, /* br_range */ { - {0, 8, 0x7}, - { 0, 0, 0 } - }, /* cond_field */ + {0, 8, 0x7, FALSE}, + {0, 0, 0, FALSE} + }, /* cond_field */ { { - INSN_BEQ_R5 /* beq $rt, $r5, label */ + INSN_BEQS38 << 16 /* beq $rt, $R5, label */ }, /* BR_RANGE_S256 */ { - INSN_BEQ_R5 /* beq $rt, $r5, label */ + INSN_BEQ_R5 /* beq $rt, $R5, label */ }, /* BR_RANGE_S16K */ { - INSN_BNE_R5, /* bne $rt, $r5, $1 */ + INSN_BNE_R5, /* bne $rt, $R5, $1 */ INSN_J /* j label */ }, /* BR_RANGE_S64K */ { - INSN_BNE_R5, /* bne $rt, $r5, $1 */ + INSN_BNE_R5, /* bne $rt, $R5, $1 */ INSN_J /* j label */ }, /* BR_RANGE_S16M */ { - INSN_BNE_R5, /* bne $rt, $r5, $1 */ + INSN_BNE_R5, /* bne $rt, $R5, $1 */ INSN_SETHI_TA, /* sethi $ta, label */ INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JR_TA /* jr $ta */ } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + }, /* relax_code_seq */ { { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 8, 0x7, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S256 */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S64K */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16M */ { - {0, 20, 0x1F}, - {0, 0, 0} + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ - {4, 4, 8, 8, 16}, /* relax_code_size */ - {4, 4, 4, 4, 4}, /* relax_branch_isize */ + }, /* relax_code_condition */ + {2, 4, 8, 8, 16}, /* relax_code_size */ + {2, 4, 4, 4, 4}, /* relax_branch_isize */ { { - {0, 4, NDS32_ORIGIN, BFD_RELOC_NDS32_17_PCREL}, - {0, 2, NDS32_CONVERT, BFD_RELOC_NDS32_9_PCREL}, + {0, 2, 0, BFD_RELOC_NDS32_9_PCREL}, {0, 0, 0, 0} }, /* BR_RANGE_S256 */ { @@ -1644,28 +1650,33 @@ static relax_info_t relax_table[] = {0, 0, 0, 0} }, /* BR_RANGE_S16K */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2}, - {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} }, /* BR_RANGE_S64K */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 8, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP2}, - {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, + {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, + {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} }, /* BR_RANGE_S16M */ { - {0, 4, NDS32_ORIGIN| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_15_PCREL}, - {0, 2, NDS32_CONVERT| NDS32_CREATE_LABLE, BFD_RELOC_NDS32_9_PCREL}, - {0, 16, NDS32_RELAX, BFD_RELOC_NDS32_LONGJUMP3}, - {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_ORIGIN, 0}, - {12, 2, NDS32_CONVERT, 0}, - {0, 0, 0, 0} + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, + {4, 4, 0, BFD_RELOC_NDS32_HI20}, + {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, + {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, + {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, + {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, + {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ }, @@ -1673,60 +1684,60 @@ static relax_info_t relax_table[] = "beqc", /* opcode */ BR_RANGE_S256, /* br_range */ { - {0, 8, 0x7FF}, - {0, 20, 0x1F}, - {0, 0, 0} - }, /* cond_field */ + {0, 8, 0x7FF, TRUE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, /* cond_field */ { { INSN_BEQC /* beqc $rt, imm11s, label */ }, /* BR_RANGE_S256 */ { - INSN_MOVI_TA, /* movi $ta, imm11s */ + INSN_MOVI_TA, /* movi $ta, imm11s */ INSN_BEQ_TA /* beq $rt, $ta, label */ }, /* BR_RANGE_S16K */ { - INSN_MOVI_TA, /* movi $ta, imm11s */ - INSN_BEQ_TA /* beq $rt, $ta, label */ + INSN_BNEC, /* bnec $rt, imm11s, $1 */ + INSN_J /* j label */ }, /* BR_RANGE_S64K */ { - INSN_BNEC, /* bnec $rt, imm11s, $1 */ + INSN_BNEC, /* bnec $rt, imm11s, $1 */ INSN_J /* j label */ }, /* BR_RANGE_S16M */ { - INSN_BNEC, /* bnec $rt, imm11s, $1 */ + INSN_BNEC, /* bnec $rt, imm11s, $1 */ INSN_SETHI_TA, /* sethi $ta, label */ INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JR_TA /* jr $ta */ } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + }, /* relax_code_seq */ { { - {0, 8, 0x7FF}, - {0, 20, 0x1F}, - {0, 0, 0} + {0, 8, 0x7FF, TRUE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S256 */ { - {0, 0, 0xFFFFF}, - {4, 20, 0x1F}, - {0, 0, 0} + {0, 0, 0xFFFFF, FALSE}, + {4, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16K */ { - {0, 0, 0xFFFFF}, - {4, 20, 0x1F}, - {0, 0, 0} + {0, 8, 0x7FF, FALSE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S64K */ { - {0, 8, 0x7FF}, - {0, 20, 0x1F}, - {0, 0, 0} + {0, 8, 0x7FF, FALSE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16M */ { - {0, 8, 0x7FF}, - {0, 20, 0x1F}, - {0, 0, 0} + {0, 8, 0x7FF, FALSE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ + }, /* relax_code_condition */ {4, 8, 8, 8, 16}, /* relax_code_size */ {4, 4, 4, 4, 4}, /* relax_branch_isize */ { @@ -1735,24 +1746,26 @@ static relax_info_t relax_table[] = {0, 0, 0, 0} }, /* BR_RANGE_S256 */ { + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7}, {4, 4, 0, BFD_RELOC_NDS32_15_PCREL}, {0, 0, 0, 0} }, /* BR_RANGE_S16K */ { - {4, 4, 0, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_WORD_9_PCREL}, + {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, {0, 0, 0, 0} }, /* BR_RANGE_S64K */ { - {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_WORD_9_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_WORD_9_PCREL}, {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, {0, 0, 0, 0} }, /* BR_RANGE_S16M */ { - {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_WORD_9_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_WORD_9_PCREL}, {4, 4, 0, BFD_RELOC_NDS32_HI20}, - {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_ORIGIN, 0}, - {12, 2, NDS32_CONVERT, 0}, + {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, + {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ @@ -1761,60 +1774,60 @@ static relax_info_t relax_table[] = "bnec", /* opcode */ BR_RANGE_S256, /* br_range */ { - {0, 8, 0x7FF}, - {0, 20, 0x1F}, - {0, 0, 0} - }, /* cond_field */ + {0, 8, 0x7FF, TRUE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} + }, /* cond_field */ { { INSN_BNEC /* bnec $rt, imm11s, label */ }, /* BR_RANGE_S256 */ { - INSN_MOVI_TA, /* movi $ta, imm11s */ + INSN_MOVI_TA, /* movi $ta, imm11s */ INSN_BNE_TA /* bne $rt, $ta, label */ }, /* BR_RANGE_S16K */ { - INSN_MOVI_TA, /* movi $ta, imm11s */ - INSN_BNE_TA /* bne $rt, $ta, label */ + INSN_BEQC, /* beqc $rt, imm11s, $1 */ + INSN_J /* j label */ }, /* BR_RANGE_S64K */ { - INSN_BEQC, /* beqc $rt, imm11s, $1 */ + INSN_BEQC, /* beqc $rt, imm11s, $1 */ INSN_J /* j label */ }, /* BR_RANGE_S16M */ { - INSN_BEQC, /* beqc $rt, imm11s, $1 */ + INSN_BEQC, /* beqc $rt, imm11s, $1 */ INSN_SETHI_TA, /* sethi $ta, label */ INSN_ORI_TA, /* ori $ta, $ta, label */ INSN_JR_TA /* jr $ta */ } /* BR_RANGE_U4G */ - }, /* relax_code_seq */ + }, /* relax_code_seq */ { { - {0, 8, 0x7FF}, - {0, 20, 0x1F}, - {0, 0, 0} + {0, 8, 0x7FF, TRUE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S256 */ { - {0, 0, 0xFFFFF}, - {4, 20, 0x1F}, - {0, 0, 0} + {0, 0, 0xFFFFF, FALSE}, + {4, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16K */ { - {0, 0, 0xFFFFF}, - {4, 20, 0x1F}, - {0, 0, 0} + {0, 8, 0x7FF, FALSE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S64K */ { - {0, 8, 0x7FF}, - {0, 20, 0x1F}, - {0, 0, 0} + {0, 8, 0x7FF, FALSE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} }, /* BR_RANGE_S16M */ { - {0, 8, 0x7FF}, - {0, 20, 0x1F}, - {0, 0, 0} + {0, 8, 0x7FF, FALSE}, + {0, 20, 0x1F, FALSE}, + {0, 0, 0, FALSE} } /* BR_RANGE_U4G */ - }, /* relax_code_condition */ + }, /* relax_code_condition */ {4, 8, 8, 8, 16}, /* relax_code_size */ {4, 4, 4, 4, 4}, /* relax_branch_isize */ { @@ -1823,40 +1836,41 @@ static relax_info_t relax_table[] = {0, 0, 0, 0} }, /* BR_RANGE_S256 */ { - {4, 4, 0, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, + {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7}, + {4, 4, 0, BFD_RELOC_NDS32_15_PCREL}, {0, 0, 0, 0} }, /* BR_RANGE_S16K */ { - {4, 4, 0, BFD_RELOC_NDS32_15_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_WORD_9_PCREL}, + {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, {0, 0, 0, 0} }, /* BR_RANGE_S64K */ { - {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_WORD_9_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_WORD_9_PCREL}, {4, 4, 0, BFD_RELOC_NDS32_25_PCREL}, {0, 0, 0, 0} }, /* BR_RANGE_S16M */ { - {0, 4, NDS32_CREATE_LABLE, BFD_RELOC_NDS32_WORD_9_PCREL}, + {0, 4, NDS32_CREATE_LABEL, BFD_RELOC_NDS32_WORD_9_PCREL}, {4, 4, 0, BFD_RELOC_NDS32_HI20}, {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, - {12, 4, NDS32_ORIGIN, 0}, - {12, 2, NDS32_CONVERT, 0}, + {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, {0, 0, 0, 0} } /* BR_RANGE_U4G */ } /* relax_fixup */ }, { - NULL, /* opcode */ - 0, /* br_range */ - {{0, 0, 0}}, /* cond_field */ - {{0}}, /* relax_code_seq */ - {{{0, 0, 0}}}, /* relax_code_condition */ - {0}, /* relax_code_size */ - {0}, /* relax_branch_isize */ - {{{0, 0, 0, 0}}}, /* relax_fixup */ + NULL, /* opcode */ + 0, /* br_range */ + {{0, 0, 0, FALSE}}, /* cond_field */ + {{0}}, /* relax_code_seq */ + {{{0, 0, 0, FALSE}}}, /* relax_code_condition */ + {0}, /* relax_code_size */ + {0}, /* relax_branch_isize */ + {{{0, 0, 0, 0}}}, /* relax_fixup */ }, }; - /* GAS definitions for command-line options. */ enum options @@ -1872,7 +1886,7 @@ enum options OPTION_OPTIMIZE_SPACE }; -const char *md_shortopts = "m:G:O"; +const char *md_shortopts = "m:O:"; struct option md_longopts[] = { {"O1", no_argument, NULL, OPTION_OPTIMIZE}, @@ -1884,6 +1898,7 @@ struct option md_longopts[] = {"meb", no_argument, NULL, OPTION_BIG}, {"mel", no_argument, NULL, OPTION_LITTLE}, {"mall-ext", no_argument, NULL, OPTION_TURBO}, + {"mext-all", no_argument, NULL, OPTION_TURBO}, {"mpic", no_argument, NULL, OPTION_PIC}, /* Relaxation related options. */ {"mno-fp-as-gp-relax", no_argument, NULL, OPTION_RELAX_FP_AS_GP_OFF}, @@ -2131,7 +2146,9 @@ static int builtin_regnum (const char *s, const char *x ATTRIBUTE_UNUSED) { struct nds32_keyword *k; - + if (*s != '$') + return -1; + s++; k = hash_find (nds32_gprs_hash, s); if (k == NULL) @@ -2177,9 +2194,9 @@ static void do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { char *arg_label = argv[0]; + relaxing = TRUE; /* b label */ - if (nds32_pic - && (strstr (arg_label, "@GOT") || strstr (arg_label, "@PLT"))) + if (nds32_pic && strstr (arg_label, "@PLT")) { md_assemblef ("sethi $ta,hi20(%s)", arg_label); md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label); @@ -2190,12 +2207,14 @@ do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { md_assemblef ("j %s", arg_label); } + relaxing = FALSE; } static void do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { char *arg_label = argv[0]; + relaxing = TRUE; /* bal|call label */ if (nds32_pic && (strstr (arg_label, "@GOT") || strstr (arg_label, "@PLT"))) @@ -2209,6 +2228,7 @@ do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { md_assemblef ("jal %s", arg_label); } + relaxing = FALSE; } static void @@ -2291,21 +2311,38 @@ do_pseudo_bral (int argc, char *argv[], int pv ATTRIBUTE_UNUSED) } static void -do_pseudo_la_internal (const char *arg_reg, const char *arg_label, const char *line) +do_pseudo_la_internal (const char *arg_reg, const char *arg_label, + const char *line) { + relaxing = TRUE; /* rt, label */ - if (!nds32_pic) + if (!nds32_pic && !strstr(arg_label, "@")) { md_assemblef ("sethi %s,hi20(%s)", arg_reg, arg_label); md_assemblef ("ori %s,%s,lo12(%s)", arg_reg, arg_reg, arg_label); } - else if ((strstr (arg_label, "@PLT") || strstr (arg_label, "@GOTOFF"))) + else if (strstr (arg_label, "@TPOFF")) + { + /* la $rt, sym@TPOFF */ + md_assemblef ("sethi $ta,hi20(%s)", arg_label); + md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label); + md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG); + } + else if (strstr(arg_label, "@GOTTPOFF")) + { + /* la $rt, sym@GOTTPOFF*/ + md_assemblef ("sethi $ta,hi20(%s)", arg_label); + md_assemblef ("lwi $ta,[$ta+lo12(%s)]", arg_label); + md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG); + } + else if (nds32_pic && ((strstr (arg_label, "@PLT") + || strstr (arg_label, "@GOTOFF")))) { md_assemblef ("sethi $ta,hi20(%s)", arg_label); md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label); md_assemblef ("add %s,$ta,$gp", arg_reg); } - else if (strstr (arg_label, "@GOT")) + else if (nds32_pic && strstr (arg_label, "@GOT")) { long addend = builtin_addend (arg_label, NULL); @@ -2327,6 +2364,7 @@ do_pseudo_la_internal (const char *arg_reg, const char *arg_label, const char *l } else as_bad (_("need PIC qualifier with symbol. '%s'"), line); + relaxing = FALSE; } static void @@ -2390,16 +2428,36 @@ do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[], int pv) if (builtin_isreg (argv[1], NULL)) { /* lwi */ - md_assemblef ("%c%c%si %s,[%s]", ls, size, argv[0], argv[1]); + md_assemblef ("%c%ci %s,[%s]", ls, size, argv[0], argv[1]); } else if (!nds32_pic) { - /* lwi */ - md_assemblef ("sethi $ta,hi20(%s)", argv[1]); - md_assemblef ("%c%c%si %s,[$ta+lo12(%s)]", ls, size, sign, argv[0], argv[1]); + relaxing = TRUE; + if (strstr (argv[1], "@TPOFF")) + { + /* ls.w $rt, sym@TPOFF */ + md_assemblef ("sethi $ta,hi20(%s)", argv[1]); + md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]); + md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG); + } + else if (strstr (argv[1], "@GOTTPOFF")) + { + /* ls.w $rt, sym@GOTTPOFF */ + md_assemblef ("sethi $ta,hi20(%s)", argv[1]); + md_assemblef ("lwi $ta,[$ta+lo12(%s)]", argv[1]); + md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG); + } + else + { + /* lwi */ + md_assemblef ("sethi $ta,hi20(%s)", argv[1]); + md_assemblef ("%c%c%si %s,[$ta+lo12(%s)]", ls, size, sign, argv[0], argv[1]); + } + relaxing = FALSE; } else { + relaxing = TRUE; /* PIC code. */ if (strstr (argv[1], "@GOTOFF")) { @@ -2430,6 +2488,7 @@ do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[], int pv) { as_bad (_("needs @GOT or @GOTOFF. %s"), argv[argc]); } + relaxing = FALSE; } } @@ -2464,7 +2523,7 @@ static void do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[], int pv) { char *arg_rt = argv[0]; - char *arg_inc = argv[2]; + char *arg_inc = argv[1]; char ls = 'r'; char size = 'x'; const char *sign = ""; @@ -2521,18 +2580,25 @@ do_pseudo_move_reg_internal (char *dst, char *src) static void do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { + expressionS exp; + + parse_expression (argv[1], &exp); + if (builtin_isreg (argv[1], NULL)) do_pseudo_move_reg_internal (argv[0], argv[1]); + else if (exp.X_op == O_constant) + /* move $rt, imm -> li $rt, imm */ + do_pseudo_li_internal (argv[0], exp.X_add_number); else - /* move $rt, imm -> li $rt, imm */ - do_pseudo_li (argc, argv, PV_DONT_CARE); + /* l.w $rt, var -> l.w $rt, var */ + do_pseudo_ls_bhw (argc, argv, 2); } static void do_pseudo_neg (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) { - md_assemble ("movi $ta,0"); - md_assemblef ("sub %s,$ta,%s", argv[0], argv[1]); + /* Instead of "subri". */ + md_assemblef ("subri %s,%s,0", argv[0], argv[1]); } static void @@ -2586,10 +2652,21 @@ do_pseudo_pushpopm (int argc, char *argv[], int pv ATTRIBUTE_UNUSED) /* Adjust $re, $rb. */ if (rb >= 28) rb = re = 31; - else if (re >= 28) + else if (nds32_gpr16 != 1 && re >= 28) re = 27; - md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4); + /* Reduce register. */ + if (nds32_gpr16 && re > 10 && !(rb == 31 && re == 31)) + { + if (re >= 15 && strstr(opc, "smw") != NULL) + md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4); + if (rb <= 10) + md_assemblef ("%s $r%d,[$sp],$r10, 0x0", opc, rb); + if (re >= 15 && strstr(opc, "lmw") != NULL) + md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4); + } + else + md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4); } static void @@ -2842,7 +2919,7 @@ struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] = {"swi.p", 3, do_pseudo_ls_bhwi, 2 | 0x80000000, 0}, {"lbsi.p", 3, do_pseudo_ls_bhwi, 0 | 0x10, 0}, {"lhsi.p", 3, do_pseudo_ls_bhwi, 1 | 0x10, 0}, - {"lwsi.p", 3, do_pseudo_ls_bhwi, 0 | 0x10, 0}, + {"lwsi.p", 3, do_pseudo_ls_bhwi, 2 | 0x10, 0}, {"move", 2, do_pseudo_move, 0, 0}, {"neg", 2, do_pseudo_neg, 0, 0}, @@ -3138,7 +3215,11 @@ nds32_parse_option (int c, char *arg) break; default: /* Determination of which option table to search for to save time. */ + if (!arg) + return 0; + ptr_arg = strchr (arg, '='); + if (ptr_arg) { /* Find the value after '='. */ @@ -3155,17 +3236,17 @@ nds32_parse_option (int c, char *arg) } else { - for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++) - { - int disable = 0; + int disable = 0; - /* Filter out the Disable option first. */ - if (strncmp (arg, "no-", 3) == 0) - { - disable = 1; - arg += 3; - } + /* Filter out the Disable option first. */ + if (strncmp (arg, "no-", 3) == 0) + { + disable = 1; + arg += 3; + } + for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++) + { if (strcmp (arg, fine_tune->name) == 0) { if (fine_tune->var != NULL) @@ -3409,12 +3490,8 @@ nds32_aligned_cons (int idx) exp.X_add_number = 0; exp.X_op = O_constant; - fix_new_exp (frag_now, - frag_now_fix () - (1 << idx), - 1 << idx, - &exp, - 0, - BFD_RELOC_NDS32_DATA); + fix_new_exp (frag_now, frag_now_fix () - (1 << idx), 1 << idx, + &exp, 0, BFD_RELOC_NDS32_DATA); } } @@ -3528,12 +3605,14 @@ nds32_omit_fp_begin (int mode) exp.X_add_symbol = abs_section_sym; if (mode == 1) { + in_omit_fp = 1; exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG; fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0, BFD_RELOC_NDS32_RELAX_REGION_BEGIN); } else { + in_omit_fp = 0; exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG; fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0, BFD_RELOC_NDS32_RELAX_REGION_END); @@ -3649,6 +3728,7 @@ nds32_relax_hint (int mode ATTRIBUTE_UNUSED) group = group->next; group->next = new; } + relaxing = TRUE; } /* Decide the size of vector entries, only accepts 4 or 16 now. */ @@ -3795,12 +3875,23 @@ void nds32_pre_do_align (int n, char *fill, int len, int max) { /* Only make a frag if we HAVE to... */ + fragS *fragP; if (n != 0 && !need_pass_2) { if (fill == NULL) { if (subseg_text_p (now_seg)) - frag_align_code (n, max); + { + fragP = frag_now; + frag_align_code (n, max); + + /* Tag this alignment when there is a lable before it. */ + if (label_exist) + { + fragP->tc_frag_data.flag = NDS32_FRAG_LABEL; + label_exist = 0; + } + } else frag_align (n, 0, max); } @@ -3888,7 +3979,7 @@ md_begin (void) /* Initial general pupose registers hash table. */ nds32_gprs_hash = hash_new (); - for (k = nds32_gprs; k->name; k++) + for (k = keyword_gpr; k->name; k++) hash_insert (nds32_gprs_hash, k->name, k); /* Initial branch hash table. */ @@ -3898,6 +3989,7 @@ md_begin (void) /* Initial relax hint hash table. */ nds32_hint_hash = hash_new (); + enable_16bit = nds32_16bit_ext; } /* HANDLE_ALIGN in write.c. */ @@ -3965,6 +4057,8 @@ nds32_frob_label (symbolS *label) int nds32_start_label (int asmdone ATTRIBUTE_UNUSED, int secdone ATTRIBUTE_UNUSED) { + if (optimize && subseg_text_p (now_seg)) + label_exist = 1; return 1; } @@ -4009,19 +4103,19 @@ get_range_type (const struct nds32_field *field) /* Save pseudo instruction relocation list. */ static struct nds32_relocs_pattern* -nds32_elf_save_pseudo_pattern (int reloc, struct nds32_asm_insn *insn, +nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_opcode *opcode, char *out, symbolS *sym, - struct nds32_relocs_pattern *reloc_ptr) + struct nds32_relocs_pattern *reloc_ptr, + fragS *fragP) { if (!reloc_ptr) reloc_ptr = malloc (sizeof (struct nds32_relocs_pattern)); reloc_ptr->seg = now_seg; reloc_ptr->sym = sym; - reloc_ptr->frag = frag_now; + reloc_ptr->frag = fragP; reloc_ptr->frchain = frchain_now; - reloc_ptr->reloc = reloc; - reloc_ptr->insn = insn->opcode->value; - reloc_ptr->size = insn->opcode->isize; + reloc_ptr->fixP = fixP; + reloc_ptr->opcode = opcode; reloc_ptr->where = out; reloc_ptr->next = NULL; return reloc_ptr; @@ -4029,88 +4123,103 @@ nds32_elf_save_pseudo_pattern (int reloc, struct nds32_asm_insn *insn, /* Check X_md to transform relocation. */ -static void -nds32_elf_record_fixup_exp (char *str, const struct nds32_field *fld, +static fixS* +nds32_elf_record_fixup_exp (fragS *fragP, char *str, + const struct nds32_field *fld, expressionS *pexp, char* out, struct nds32_asm_insn *insn) { int reloc = -1; - symbolS *sym = NULL; - struct nds32_relocs_group *group; - struct nds32_relocs_pattern *reloc_ptr; + expressionS exp; + fixS *fixP = NULL; /* Handle instruction relocation. */ if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_HI20)) { /* Relocation for hi20 modifier. */ - sym = pexp->X_add_symbol; switch (pexp->X_md) { - case BFD_RELOC_NDS32_GOTOFF: - /* @GOTOFF */ + case BFD_RELOC_NDS32_GOTOFF: /* @GOTOFF */ reloc = BFD_RELOC_NDS32_GOTOFF_HI20; break; - case BFD_RELOC_NDS32_GOT20: - /* @GOT */ + case BFD_RELOC_NDS32_GOT20: /* @GOT */ reloc = BFD_RELOC_NDS32_GOT_HI20; break; - case BFD_RELOC_NDS32_25_PLTREL: - /* @PLT */ + case BFD_RELOC_NDS32_25_PLTREL: /* @PLT */ if (!nds32_pic) as_bad (_("Invalid PIC expression.")); else reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20; break; - default: - /* No suffix. */ + case BFD_RELOC_NDS32_GOTPC20: /* _GLOBAL_OFFSET_TABLE_ */ + reloc = BFD_RELOC_NDS32_GOTPC_HI20; + break; + case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */ + reloc = BFD_RELOC_NDS32_TLS_LE_HI20; + break; + case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */ + reloc = BFD_RELOC_NDS32_TLS_IE_HI20; + break; + default: /* No suffix. */ reloc = BFD_RELOC_NDS32_HI20; break; } - - fix_new_exp (frag_now, out - frag_now->fr_literal, - insn->opcode->isize, insn->info, 0 /* pcrel */, - reloc); + fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, + insn->info, 0 /* pcrel */, reloc); } else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_LO12)) { /* Relocation for lo12 modifier. */ if (fld->bitsize == 15 && fld->shift == 0) { + /* [ls]bi || ori */ switch (pexp->X_md) { - case BFD_RELOC_NDS32_GOTOFF: - /* @GOTOFF */ + case BFD_RELOC_NDS32_GOTOFF: /* @GOTOFF */ reloc = BFD_RELOC_NDS32_GOTOFF_LO12; break; - case BFD_RELOC_NDS32_GOT20: - /* @GOT */ + case BFD_RELOC_NDS32_GOT20: /* @GOT */ reloc = BFD_RELOC_NDS32_GOT_LO12; break; - case BFD_RELOC_NDS32_25_PLTREL: - /* @PLT */ + case BFD_RELOC_NDS32_25_PLTREL: /* @PLT */ if (!nds32_pic) as_bad (_("Invalid PIC expression.")); else reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12; break; - default: - /* No suffix. */ - reloc = BFD_RELOC_NDS32_LO12S0; /* [ls]bi || ori */ + case BFD_RELOC_NDS32_GOTPC20: /* _GLOBAL_OFFSET_TABLE_ */ + reloc = BFD_RELOC_NDS32_GOTPC_LO12; + break; + case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */ + reloc = BFD_RELOC_NDS32_TLS_LE_LO12; + break; + default: /* No suffix. */ + reloc = BFD_RELOC_NDS32_LO12S0; break; } } else if (fld->bitsize == 15 && fld->shift == 1) reloc = BFD_RELOC_NDS32_LO12S1; /* [ls]hi */ else if (fld->bitsize == 15 && fld->shift == 2) - reloc = BFD_RELOC_NDS32_LO12S2; /* [ls]wi */ + { + /* [ls]wi */ + switch (pexp->X_md) + { + case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */ + reloc = BFD_RELOC_NDS32_TLS_IE_LO12S2; + break; + default: /* No suffix. */ + reloc = BFD_RELOC_NDS32_LO12S2; + break; + } + } else if (fld->bitsize == 15 && fld->shift == 3) reloc = BFD_RELOC_NDS32_LO12S3; /* [ls]di */ else if (fld->bitsize == 12 && fld->shift == 2) - reloc = BFD_RELOC_NDS32_LO12S2; /* f[ls][sd]i */ + reloc = R_NDS32_LO12S2_SP_RELA; /* f[ls][sd]i */ - fix_new_exp (frag_now, out - frag_now->fr_literal, - insn->opcode->isize, insn->info, 0 /* pcrel */, - reloc); + fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, + insn->info, 0 /* pcrel */, reloc); } else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4 && (insn->attr & NASM_ATTR_PCREL)) @@ -4127,9 +4236,8 @@ nds32_elf_record_fixup_exp (char *str, const struct nds32_field *fld, else abort (); - fix_new_exp (frag_now, out - frag_now->fr_literal, - insn->opcode->isize, insn->info, 1 /* pcrel */, - reloc); + fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, + insn->info, 1 /* pcrel */, reloc); } else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4 && (insn->attr & NASM_ATTR_GPREL)) @@ -4144,9 +4252,16 @@ nds32_elf_record_fixup_exp (char *str, const struct nds32_field *fld, else abort (); - fix_new_exp (frag_now, out - frag_now->fr_literal, - insn->opcode->isize, insn->info, 0 /* pcrel */, - reloc); + fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, + insn->info, 0 /* pcrel */, reloc); + /* Insert INSN16 for converting fp_as_gp. */ + exp.X_op = O_symbol; + exp.X_add_symbol = abs_section_sym; + exp.X_add_number = 0; + if (in_omit_fp && reloc == BFD_RELOC_NDS32_SDA17S2) + fix_new_exp (fragP, out - fragP->fr_literal, + insn->opcode->isize, &exp, 0 /* pcrel */, + BFD_RELOC_NDS32_INSN16); } else if (fld && fld->bitpos == 0 && insn->opcode->isize == 2 && (insn->attr & NASM_ATTR_PCREL)) @@ -4157,20 +4272,50 @@ nds32_elf_record_fixup_exp (char *str, const struct nds32_field *fld, else abort (); - fix_new_exp (frag_now, out - frag_now->fr_literal, - insn->opcode->isize, insn->info, 1 /* pcrel */, - reloc); + fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, + insn->info, 1 /* pcrel */, reloc); } - else if (fld) - { - as_bad (_("Don't know how to handle this field. %s"), - str); + else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_IFC_EXT)) + { + /* Relocation for ifcall instruction. */ + if (insn->opcode->isize == 2 && fld->bitsize == 9 && fld->shift == 1) + reloc = BFD_RELOC_NDS32_10IFCU_PCREL; + else if (insn->opcode->isize == 4 && fld->bitsize == 16 + && fld->shift == 1) + reloc = BFD_RELOC_NDS32_17IFC_PCREL; + else + abort (); + + fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, + insn->info, 1 /* pcrel */, reloc); } + else if (fld) + as_bad (_("Don't know how to handle this field. %s"), str); + + return fixP; +} + +/* Build instruction pattern to relax. There are two type group pattern + including pseudo instruction and relax hint. */ + +static void +nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out, + struct nds32_opcode *opcode, fragS *fragP, + const struct nds32_field *fld) +{ + struct nds32_relocs_pattern *reloc_ptr; + struct nds32_relocs_group *group; + symbolS *sym = NULL; + + /* The expression may be used uninitialized. */ + if (fld) + sym = pexp->X_add_symbol; if (pseudo_opcode) { /* Save instruction relation for pseudo instruction expanding pattern. */ - reloc_ptr = nds32_elf_save_pseudo_pattern (reloc, insn, out, sym, NULL); + reloc_ptr = nds32_elf_save_pseudo_pattern (fixP, opcode, out, sym, + NULL, fragP); if (!relocs_list) relocs_list = reloc_ptr; else @@ -4187,267 +4332,120 @@ nds32_elf_record_fixup_exp (char *str, const struct nds32_field *fld, group = nds32_relax_hint_current; while (group) { - nds32_elf_save_pseudo_pattern (reloc, insn, out, sym, group->pattern); + nds32_elf_save_pseudo_pattern (fixP, opcode, out, sym, + group->pattern, fragP); group = group->next; free (nds32_relax_hint_current); nds32_relax_hint_current = group; } } + + /* Set relaxing false only for relax_hint trigger it. */ + if (!pseudo_opcode) + relaxing = FALSE; } -#define N32_MEM_EXT(insn) (N32_OP6_MEM<< 25| insn) +#define N32_MEM_EXT(insn) ((N32_OP6_MEM << 25) | insn) /* Relax pattern for link time relaxation. */ -static struct nds32_relocation_map relocation_table[] = +static struct nds32_relax_hint_table relax_ls_table[] = { + { + /* Set address: la -> sethi ori. */ + NDS32_RELAX_HINT_LA, /* main_type */ + 8, /* relax_code_size */ { - /* Load-Store: sethi lwi+ - Load address: sethi ori */ - BFD_RELOC_NDS32_HI20, /* main_type */ - { - { - {BFD_RELOC_NDS32_LOADSTORE, 0}, - {0, 0} - }, - { - {BFD_RELOC_NDS32_INSN16, 0}, - {0, 0} - }, - { - {0, 0} - } - }, - }, - { - /* Load-Store: sethi ori lwi+ - Load address: sethi ori add */ - BFD_RELOC_NDS32_GOTOFF_HI20, /* main_type */ - { - { - {BFD_RELOC_NDS32_LOADSTORE, 0}, - {0, 0} - }, - { - {BFD_RELOC_NDS32_INSN16, 0}, - {BFD_RELOC_NDS32_PTR, 0}, - {BFD_RELOC_NDS32_PTR_COUNT, 0}, - {0, 0} - }, - { - {BFD_RELOC_NDS32_GOTOFF_SUFF, 0}, - {BFD_RELOC_NDS32_PTR_RESOLVED, 0}, - {0, 0} - }, - { - {0, 0} - } - }, - }, + OP6 (SETHI), + OP6 (ORI), + }, /* relax_code_seq */ { - /* Load-Store: sethi ori lw lwi+ - Load address: sethi ori lw [addi|add] */ - BFD_RELOC_NDS32_GOT_HI20, /* main_type */ - { - { - {BFD_RELOC_NDS32_LOADSTORE, 0}, - {0, 0} - }, - { - {BFD_RELOC_NDS32_INSN16, 0}, - /* For pseudo la and l.w. - Lw is the next one instruction. */ - {BFD_RELOC_NDS32_PTR, N32_MEM_EXT (N32_MEM_LW)}, - {BFD_RELOC_NDS32_PTR_COUNT, 0}, - {0, 0} - }, - { - {BFD_RELOC_NDS32_GOT_SUFF, N32_MEM_EXT (N32_MEM_LW)}, - {BFD_RELOC_NDS32_PTR_RESOLVED, N32_MEM_EXT (N32_MEM_LW)}, - {0, 0} - }, - { - {0, 0}, - }, - }, - }, + {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, + {4, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_INSN16} + } /* relax_fixup */ + }, + { + /* Set address: l.w -> sethi ori. */ + NDS32_RELAX_HINT_LS, /* main_type */ + 8, /* relax_code_size */ { - BFD_RELOC_NDS32_PLT_GOTREL_HI20, /* main_type */ - { - { - {BFD_RELOC_NDS32_LOADSTORE, 0}, - {0, 0} - }, - { - {BFD_RELOC_NDS32_INSN16, 0}, - /* For pseudo bal. - jral is the target instruction. */ - {BFD_RELOC_NDS32_PTR, INSN_JRAL}, - {BFD_RELOC_NDS32_PTR, (INSN_JRAL | (REG_LP << 20))}, - {BFD_RELOC_NDS32_PTR_COUNT, 0}, - {0, 0} - }, - { - /* For pseudo bal. - jral is the target instruction. */ - {BFD_RELOC_NDS32_PTR, INSN_JRAL}, - {BFD_RELOC_NDS32_PTR, (INSN_JRAL | (REG_LP << 20))}, - {BFD_RELOC_NDS32_PTR_COUNT, 0}, - {0, 0} - }, - { - {BFD_RELOC_NDS32_PLT_GOT_SUFF, 0}, - {BFD_RELOC_NDS32_PTR_RESOLVED, 0}, - {0, 0} - }, - { - {0, 0}, - }, - }, - }, + OP6 (SETHI), + OP6 (LBI), + }, /* relax_code_seq */ { - 0, - { - { - {0, 0}, - }, - }, - } + {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, + {4, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_INSN16} + } /* relax_fixup */ + }, + { + 0, + 0, + {0}, + {{0, 0 , 0, 0}} + } }; /* Since sethi loadstore relocation has to using next instruction to determine elimination itself or not, we have to return the next instruction range. */ static int -nds32_elf_sethi_range (struct nds32_relocs_pattern *relocs_ptr) -{ - unsigned int insn = relocs_ptr->insn; - int range; - switch (insn) - { - case INSN_LBI: - case INSN_SBI: - case INSN_LBSI: - case N32_MEM_EXT (N32_MEM_LB): - case N32_MEM_EXT (N32_MEM_LBS): - case N32_MEM_EXT (N32_MEM_SB): - range = 0x01; - break; - case INSN_LHI: - case INSN_SHI: - case INSN_LHSI: - case N32_MEM_EXT (N32_MEM_LH): - case N32_MEM_EXT (N32_MEM_LHS): - case N32_MEM_EXT (N32_MEM_SH): - range = 0x02; - break; - case INSN_LWI: - case INSN_SWI: - case N32_MEM_EXT (N32_MEM_LW): - case N32_MEM_EXT (N32_MEM_SW): - range = 0x04; - break; - case INSN_FLSI: - case INSN_FSSI: - range = 0x08; - break; - case INSN_FLDI: - case INSN_FSDI: - range = 0x10; - break; - case INSN_ORI: - range = 0x20; - break; - default: - range = 0x0; - break; +nds32_elf_sethi_range (struct nds32_relocs_pattern *pattern) +{ + int range = 0; + while (pattern) + { + switch (pattern->opcode->value) + { + case INSN_LBI: + case INSN_SBI: + case INSN_LBSI: + case N32_MEM_EXT (N32_MEM_LB): + case N32_MEM_EXT (N32_MEM_LBS): + case N32_MEM_EXT (N32_MEM_SB): + range = NDS32_LOADSTORE_BYTE; + break; + case INSN_LHI: + case INSN_SHI: + case INSN_LHSI: + case N32_MEM_EXT (N32_MEM_LH): + case N32_MEM_EXT (N32_MEM_LHS): + case N32_MEM_EXT (N32_MEM_SH): + range = NDS32_LOADSTORE_HALF; + break; + case INSN_LWI: + case INSN_SWI: + case N32_MEM_EXT (N32_MEM_LW): + case N32_MEM_EXT (N32_MEM_SW): + range = NDS32_LOADSTORE_WORD; + break; + case INSN_FLSI: + case INSN_FSSI: + range = NDS32_LOADSTORE_FLOAT_S; + break; + case INSN_FLDI: + case INSN_FSDI: + range = NDS32_LOADSTORE_FLOAT_D; + break; + case INSN_ORI: + range = NDS32_LOADSTORE_IMM; + break; + default: + range = NDS32_LOADSTORE_NONE; + break; + } + if (range != NDS32_LOADSTORE_NONE) + break; + pattern = pattern->next; } return range; } /* The args means: instruction size, the 1st instruction is converted to 16 or not, optimize option, 16 bit instruction is enable. */ -#define SET_ADDEND( size, convertible, optimize, insn16_on ) \ +#define SET_ADDEND(size, convertible, optimize, insn16_on) \ (((size) & 0xff) | ((convertible) ? 1 << 31 : 0) \ | ((optimize) ? 1<< 30 : 0) | (insn16_on ? 1 << 29 : 0)) -/* Insert new fix. */ - -static void -nds32_elf_insert_relocation (struct nds32_relocs_pattern *pattern, unsigned int reloc, - unsigned int insn_mask, symbolS *sym) -{ - expressionS exp; - symbolS *sym_t; - struct nds32_relocs_pattern *pattern_t; - int range; - fragS *frag = pattern->frag; - char *out = pattern->where; - unsigned int size = pattern->size; - static int ptr_count = 0; - - exp.X_op = O_symbol; - exp.X_add_symbol = abs_section_sym; - exp.X_add_number = 0; - - switch (reloc) - { - case BFD_RELOC_NDS32_LOADSTORE: - /* To get the sethi match pattern. */ - range = nds32_elf_sethi_range (pattern->next); - exp.X_add_number = SET_ADDEND (4 /* size */, 0, optimize, enable_16bit); - exp.X_add_number |= ((range & 0x3f) << 8); - fix_new_exp (frag, out - frag->fr_literal, size, &exp, 0 /* pcrel */, reloc); - break; - - case BFD_RELOC_NDS32_PTR: - pattern_t = pattern->next; - while (pattern_t) - { - if (insn_mask == 0 || pattern_t->insn == insn_mask) - { - sym_t = symbol_temp_new (pattern_t->seg, - pattern_t->where - pattern_t->frag->fr_literal, - pattern_t->frag); - exp.X_add_symbol = sym_t; - fix_new_exp (frag, out - frag->fr_literal, 0, &exp, 0 /* pcrel */, reloc); - ptr_count++; - break; - } - pattern_t = pattern_t->next; - } - break; - - case BFD_RELOC_NDS32_PTR_COUNT: - /* In current design, it only be referanced once. */ - if (ptr_count != 0) - { - exp.X_add_number = ptr_count; - fix_new_exp (frag, out - frag->fr_literal, size, &exp, 0, reloc); - } - ptr_count = 0; - break; - - case BFD_RELOC_NDS32_GOTOFF_SUFF: - case BFD_RELOC_NDS32_GOT_SUFF: - case BFD_RELOC_NDS32_PLT_GOT_SUFF: - /* It has to record symbol. */ - if (insn_mask == 0 || pattern->insn == insn_mask) - { - exp.X_add_symbol = sym; - fix_new_exp (frag, out - frag->fr_literal, size, &exp, 0, reloc); - } - break; - - case BFD_RELOC_NDS32_PTR_RESOLVED: - default: - if (insn_mask == 0 || pattern->insn == insn_mask) - { - fix_new_exp (frag, out - frag->fr_literal, size, &exp, 0, reloc); - } - } -} - static void nds32_set_elf_flags_by_insn (struct nds32_asm_insn * insn) { @@ -4562,58 +4560,525 @@ nds32_set_elf_flags_by_insn (struct nds32_asm_insn * insn) /* TODO: E_NDS32_HAS_SATURATION_INST */ } +/* Flag for analysis relaxation type. */ + +enum nds32_insn_type +{ + N32_RELAX_SETHI = 1, + N32_RELAX_BR = (1 << 1), + N32_RELAX_LSI = (1 << 2), + N32_RELAX_JUMP = (1 << 3), + N32_RELAX_CALL = (1 << 4), + N32_RELAX_ORI = (1 << 5), + N32_RELAX_MEM = (1 << 6), + N32_RELAX_MOVI = (1 << 7), +}; + +struct nds32_hint_map +{ + bfd_reloc_code_real_type hi_type; + char *opc; + enum nds32_relax_hint_type hint_type; + enum nds32_br_range range; + enum nds32_insn_type insn_list; +}; + +/* Table to match instructions with hint and relax pattern. */ + +static struct nds32_hint_map hint_map [] = +{ + { + /* LONGCALL4. */ + BFD_RELOC_NDS32_HI20, + "jal", + NDS32_RELAX_HINT_NONE, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL + }, + { + /* LONGCALL5. */ + _dummy_first_bfd_reloc_code_real, + "bgezal", + NDS32_RELAX_HINT_NONE, + BR_RANGE_S16M, + N32_RELAX_BR | N32_RELAX_CALL + }, + { + /* LONGCALL6. */ + BFD_RELOC_NDS32_HI20, + "bgezal", + NDS32_RELAX_HINT_NONE, + BR_RANGE_U4G, + N32_RELAX_BR | N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL + }, + { + /* LONGJUMP4. */ + BFD_RELOC_NDS32_HI20, + "j", + NDS32_RELAX_HINT_NONE, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_JUMP + }, + { + /* LONGJUMP5. */ + /* There is two kinds of veriation of LONGJUMP5. One of them + generate EMPTY relocation for converted INSN16 if needed. + But we don't distinguish them here. */ + _dummy_first_bfd_reloc_code_real, + "beq", + NDS32_RELAX_HINT_NONE, + BR_RANGE_S16M, + N32_RELAX_BR | N32_RELAX_JUMP + }, + { + /* LONGJUMP6. */ + BFD_RELOC_NDS32_HI20, + "beq", + NDS32_RELAX_HINT_NONE, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_BR | N32_RELAX_JUMP + }, + { + /* LONGJUMP7. */ + _dummy_first_bfd_reloc_code_real, + "beqc", + NDS32_RELAX_HINT_NONE, + BR_RANGE_S16K, + N32_RELAX_MOVI | N32_RELAX_BR + }, + { + /* LOADSTORE ADDRESS. */ + BFD_RELOC_NDS32_HI20, + NULL, + NDS32_RELAX_HINT_LA, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_ORI + }, + { + /* LOADSTORE ADDRESS. */ + BFD_RELOC_NDS32_HI20, + NULL, + NDS32_RELAX_HINT_LS, + BR_RANGE_U4G, + N32_RELAX_SETHI | N32_RELAX_LSI + }, + {0, NULL, 0, 0 ,0} +}; + +/* Find the relaxation pattern according to instructions. */ + +static bfd_boolean +nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern, + struct nds32_relax_hint_table *hint_info) +{ + unsigned int opcode, seq_size; + enum nds32_br_range range; + struct nds32_relocs_pattern *pattern, *hi_pattern = NULL; + char *opc = NULL; + relax_info_t *relax_info = NULL; + nds32_relax_fixup_info_t *fixup_info, *hint_fixup; + enum nds32_relax_hint_type hint_type = NDS32_RELAX_HINT_NONE; + struct nds32_relax_hint_table *table_ptr; + uint32_t *code_seq, *hint_code; + enum nds32_insn_type relax_type = 0; + struct nds32_hint_map *map_ptr = hint_map; + unsigned int i; + char *check_insn[] = + { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" }; + + /* TODO: PLT GOT. */ + /* Traverse all pattern instruction and set flag. */ + pattern = relocs_pattern; + while (pattern) + { + if (pattern->opcode->isize == 4) + { + /* 4 byte instruction. */ + opcode = N32_OP6 (pattern->opcode->value); + switch (opcode) + { + case N32_OP6_SETHI: + hi_pattern = pattern; + relax_type |= N32_RELAX_SETHI; + break; + case N32_OP6_MEM: + relax_type |= N32_RELAX_MEM; + break; + case N32_OP6_ORI: + relax_type |= N32_RELAX_ORI; + break; + case N32_OP6_BR1: + case N32_OP6_BR2: + case N32_OP6_BR3: + relax_type |= N32_RELAX_BR; + break; + case N32_OP6_MOVI: + relax_type |= N32_RELAX_MOVI; + break; + case N32_OP6_LBI: + case N32_OP6_SBI: + case N32_OP6_LBSI: + case N32_OP6_LHI: + case N32_OP6_SHI: + case N32_OP6_LHSI: + case N32_OP6_LWI: + case N32_OP6_SWI: + case N32_OP6_LWC: + case N32_OP6_SWC: + relax_type |= N32_RELAX_LSI; + break; + case N32_OP6_JREG: + if (__GF (pattern->opcode->value, 0, 1) == 1) + relax_type |= N32_RELAX_CALL; + else + relax_type |= N32_RELAX_JUMP; + break; + case N32_OP6_JI: + if (__GF (pattern->opcode->value, 24, 1) == 1) + relax_type |= N32_RELAX_CALL; + else + relax_type |= N32_RELAX_JUMP; + break; + default: + as_warn (_("relax hint unrecognized instruction: line %d."), + pattern->frag->fr_line); + return FALSE; + } + } + else + { + /* 2 byte instruction. Compare by opcode name because the opcode of + 2byte instruction is not regular. */ + for (i = 0; i < sizeof (check_insn) / sizeof (check_insn[0]); i++) + { + if (strcmp (pattern->opcode->opcode, check_insn[i]) == 0) + { + relax_type |= N32_RELAX_BR; + break; + } + } + if (strcmp (pattern->opcode->opcode, "movi55") == 0) + relax_type |= N32_RELAX_MOVI; + } + pattern = pattern->next; + } + + /* Analysis instruction flag to choose relaxation table. */ + while (map_ptr->insn_list != 0) + { + if (map_ptr->insn_list == relax_type + && (!hi_pattern + || (hi_pattern->fixP + && hi_pattern->fixP->fx_r_type == map_ptr->hi_type))) + { + opc = map_ptr->opc; + hint_type = map_ptr->hint_type; + range = map_ptr->range; + break; + } + map_ptr++; + } + + if (map_ptr->insn_list == 0) + { + as_warn (_("Can not find match relax hint. line : %d"), + relocs_pattern->frag->fr_line); + return FALSE; + } + + /* Get the match table. */ + if (opc) + { + /* Branch relax pattern. */ + relax_info = hash_find (nds32_relax_info_hash, opc); + if (!relax_info) + return FALSE; + fixup_info = relax_info->relax_fixup[range]; + code_seq = relax_info->relax_code_seq[range]; + seq_size = relax_info->relax_code_size[range]; + } + else if (hint_type) + { + /* Load-store relax pattern. */ + table_ptr = relax_ls_table; + while (table_ptr->main_type != 0) + { + if (table_ptr->main_type == hint_type) + { + fixup_info = table_ptr->relax_fixup; + code_seq = table_ptr->relax_code_seq; + seq_size = table_ptr->relax_code_size; + break; + } + table_ptr++; + } + if (table_ptr->main_type == 0) + return FALSE; + } + else + return FALSE; + + hint_fixup = hint_info->relax_fixup; + hint_code = hint_info->relax_code_seq; + hint_info->relax_code_size = seq_size; + + while (fixup_info->size != 0) + { + if (fixup_info->ramp & NDS32_HINT) + { + memcpy (hint_fixup, fixup_info, sizeof (nds32_relax_fixup_info_t)); + hint_fixup++; + } + fixup_info++; + } + /* Clear final relocation. */ + memset (hint_fixup, 0, sizeof (nds32_relax_fixup_info_t)); + /* Copy code sequance. */ + memcpy (hint_code, code_seq, seq_size); + return TRUE; +} + +/* Because there are a lot of variant of load-store, check + all these type here. */ + +#define CLEAN_REG(insn) ((insn) & 0xff0003ff) +static bfd_boolean +nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq) +{ + char *check_insn[] = + { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" }; + uint32_t insn = opcode->value; + unsigned int i; + + insn = CLEAN_REG (opcode->value); + if (insn == seq) + return TRUE; + + switch (seq) + { + case OP6 (LBI): + /* In relocation_table, it regards instruction LBI as representation + of all the NDS32_RELAX_HINT_LS pattern. */ + if (insn == OP6 (LBI) || insn == OP6 (SBI) || insn == OP6 (LBSI) + || insn == OP6 (LHI) || insn == OP6 (SHI) || insn == OP6 (LHSI) + || insn == OP6 (LWI) || insn == OP6 (SWI) + || insn == OP6 (LWC) || insn == OP6 (SWC)) + return TRUE; + break; + case OP6 (BR2): + /* This is for LONGCALL5 and LONGCALL6. */ + if (insn == OP6 (BR2)) + return TRUE; + break; + case OP6 (BR1): + /* This is for LONGJUMP5 and LONGJUMP6. */ + if (opcode->isize == 4 + && (insn == OP6 (BR1) || insn == OP6 (BR2) || insn == OP6 (BR3))) + return TRUE; + else if (opcode->isize == 2) + { + for (i = 0; i < sizeof (check_insn) / sizeof (check_insn[0]); i++) + if (strcmp (opcode->opcode, check_insn[i]) == 0) + return TRUE; + } + break; + case OP6 (MOVI): + /* This is for LONGJUMP7. */ + if (opcode->isize == 2 && strcmp (opcode->opcode, "movi55") == 0) + return TRUE; + break; + } + return FALSE; +} + /* Append relax relocation for link time relaxing. */ static void nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value) { - struct nds32_relocs_pattern *relocs_temp = + struct nds32_relocs_pattern *relocs_pattern = (struct nds32_relocs_pattern *) value; - unsigned int reloc, group_type, insn; - symbolS *sym; - unsigned int i = 0, x = 0, y; + struct nds32_relocs_pattern *pattern_temp, *pattern_now; + symbolS *sym, *hi_sym = NULL; + expressionS exp; + fragS *fragP; segT seg_bak = now_seg; frchainS *frchain_bak = frchain_now; + struct nds32_relax_hint_table hint_info; + nds32_relax_fixup_info_t *hint_fixup, *fixup_now; + size_t fixup_size; + offsetT branch_offset; + fixS *fixP; + int range, offset; + unsigned int ptr_offset, hint_count, relax_code_size, count = 0; + uint32_t *code_seq, code_insn; + char *where; + + if (!relocs_pattern) + return; - if (!relocs_temp) + if (!nds32_find_reloc_table (relocs_pattern, &hint_info)) return; - group_type = relocs_temp->reloc; - sym = relocs_temp->sym; + /* Save symbol for some EMPTY relocation using. */ + pattern_now = relocs_pattern; + while (pattern_now) + { + if (pattern_now->opcode->value == OP6 (SETHI)) + { + hi_sym = pattern_now->sym; + break; + } + pattern_now = pattern_now->next; + } + /* Inserting fix up must specify now_seg or frchain_now. */ - now_seg = relocs_temp->seg; - frchain_now = relocs_temp->frchain; + now_seg = relocs_pattern->seg; + frchain_now = relocs_pattern->frchain; + fragP = relocs_pattern->frag; + branch_offset = fragP->fr_offset; - /* Find pattern in relocation table. */ - while (i < (sizeof (relocation_table)/sizeof (relocation_table[0])) - &&relocation_table[i].main_type != group_type) - i++; + hint_fixup = hint_info.relax_fixup; + code_seq = hint_info.relax_code_seq; + relax_code_size = hint_info.relax_code_size; + pattern_now = relocs_pattern; - /* Can not find relocation pattern. */ - if (relocation_table[i].main_type == 0) - return; + /* Insert relaxation. */ + exp.X_op = O_symbol; - while (relocs_temp) + while (pattern_now) { - y = 0; + /* Choose the match fixup by instruction. */ + code_insn = CLEAN_REG (*(code_seq + count)); + if (!nds32_match_hint_insn (pattern_now->opcode, code_insn)) + { + count = 0; + code_insn = CLEAN_REG (*(code_seq + count)); - while (relocation_table[i].reloc_insn[x][y][0] != 0) + while (!nds32_match_hint_insn (pattern_now->opcode, code_insn)) + { + count++; + if (count >= relax_code_size / 4) + { + as_bad (_("Internal error: Relax hint error. %s: %x"), + now_seg->name, pattern_now->opcode->value); + goto restore; + } + code_insn = CLEAN_REG (*(code_seq + count)); + } + } + fragP = pattern_now->frag; + sym = pattern_now->sym; + branch_offset = fragP->fr_offset; + offset = count * 4; + where = pattern_now->where; + /* Find the instruction map fix. */ + fixup_now = hint_fixup; + while (fixup_now->offset != offset) { - reloc = relocation_table[i].reloc_insn[x][y][0]; - insn = relocation_table[i].reloc_insn[x][y][1]; - nds32_elf_insert_relocation (relocs_temp, reloc, insn, sym); - y++; + fixup_now++; + if (fixup_now->size == 0) + break; } + /* This element is without relaxation relocation. */ + if (fixup_now->size == 0) + { + pattern_now = pattern_now->next; + continue; + } + fixup_size = fixup_now->size; - /* Next instruction. */ - relocs_temp = relocs_temp->next; + /* Insert all fixup. */ + while (fixup_size != 0 && fixup_now->offset == offset) + { + /* Set the real instruction size in element. */ + fixup_size = pattern_now->opcode->isize; + if (fixup_now->ramp & NDS32_FIX) + { + /* Convert original relocation. */ + pattern_now->fixP->fx_r_type = fixup_now->r_type ; + fixup_size = 0; + } + else if ((fixup_now->ramp & NDS32_PTR) != 0) + { + /* This relocation has to point to another instruction. Make + sure each resolved relocation has to be pointed. */ + pattern_temp = relocs_pattern; + /* All instruction in relax_table should be 32-bit. */ + hint_count = hint_info.relax_code_size / 4; + code_insn = CLEAN_REG (*(code_seq + hint_count - 1)); + while (pattern_temp) + { + /* Point to every resolved relocation. */ + if (nds32_match_hint_insn (pattern_temp->opcode, code_insn)) + { + ptr_offset = + pattern_temp->where - pattern_temp->frag->fr_literal; + exp.X_add_symbol = symbol_temp_new (now_seg, ptr_offset, + pattern_temp->frag); + exp.X_add_number = 0; + fixP = + fix_new_exp (fragP, where - fragP->fr_literal, + fixup_size, &exp, 0, fixup_now->r_type); + fixP->fx_addnumber = fixP->fx_offset; + } + pattern_temp = pattern_temp->next; + } + fixup_size = 0; + } + else if (fixup_now->ramp & NDS32_ADDEND) + { + range = nds32_elf_sethi_range (relocs_pattern); + if (range == NDS32_LOADSTORE_NONE) + { + as_bad (_("Internal error: Range error. %s"), now_seg->name); + return; + } + exp.X_add_symbol = abs_section_sym; + exp.X_add_number = SET_ADDEND (4, 0, optimize, enable_16bit); + exp.X_add_number |= ((range & 0x3f) << 8); + } + else if ((fixup_now->ramp & NDS32_ABS) != 0) + { + /* This is a tag relocation. */ + exp.X_add_symbol = abs_section_sym; + exp.X_add_number = 0; + } + else if ((fixup_now->ramp & NDS32_INSN16) != 0) + { + if (!enable_16bit) + fixup_size = 0; + /* This is a tag relocation. */ + exp.X_add_symbol = abs_section_sym; + exp.X_add_number = 0; + } + else if ((fixup_now->ramp & NDS32_SYM) != 0) + { + /* For EMPTY relocation save the true symbol. */ + exp.X_add_symbol = hi_sym; + exp.X_add_number = branch_offset; + } + else + { + exp.X_add_symbol = sym; + exp.X_add_number = branch_offset; + } - /* There are load store instruction shared setting symbol part, so - re-using the final relocation. */ - if (relocation_table[i].reloc_insn[x+1][0][0] != 0) - x++; + if (fixup_size != 0) + { + fixP = fix_new_exp (fragP, where - fragP->fr_literal, + fixup_size, &exp, 0, fixup_now->r_type); + fixP->fx_addnumber = fixP->fx_offset; + } + fixup_now++; + fixup_size = fixup_now->size; + } + if (count < relax_code_size / 4) + count++; + pattern_now = pattern_now->next; } +restore: now_seg = seg_bak; frchain_now = frchain_bak; } @@ -4663,12 +5128,12 @@ md_assemble (char *str) char *out; struct nds32_pseudo_opcode *popcode; const struct nds32_field *fld = NULL; - fixS *fixP ATTRIBUTE_UNUSED; - int insn_type; + fixS *fixP; uint16_t insn_16; - uint32_t insn_32; struct nds32_relocs_pattern *relocs_temp; expressionS *pexp; + fragS *fragP; + int label = label_exist; popcode = nds32_lookup_pseudo_opcode (str); /* Note that we need to check 'verbatim' and @@ -4694,6 +5159,7 @@ md_assemble (char *str) return; } + label_exist = 0; insn.info = (expressionS *) alloca (sizeof (expressionS)); nds32_assemble (&asm_desc, &insn, str); @@ -4728,76 +5194,115 @@ md_assemble (char *str) if (!nds32_check_insn_available (insn, str)) return; - /* Create new frag if the instruction can be relaxed. */ + /* Make sure the begining of text being 2-byte align. */ + nds32_adjust_label (1); fld = insn.field; - if (!verbatim && fld && (insn.attr & NASM_ATTR_BRANCH)) + /* Try to allocate the max size to guarantee relaxable same branch + instructions in the same fragment. */ + frag_grow (NDS32_MAXCHAR); + fragP = frag_now; + if (fld && (insn.attr & NASM_ATTR_BRANCH) + && (pseudo_opcode || (insn.opcode->value != INSN_JAL + && insn.opcode->value != INSN_J)) + && (!verbatim || pseudo_opcode)) { /* User assembly code branch relax for it. */ - fragS *fragp = frag_now; - /* If fld is not NULL, it is a symbol. */ + /* Branch msut relax to proper pattern in user assembly code exclude + J and JAL. Keep these two in original type for users which wants + to keep their size be fixed. In general, assembler does not convert + instruction generated by compiler. But jump instruction may be + truncated in text virtual model. For workaround, compiler generate + pseudo jump to fix this issue currently. */ + /* Get branch range type. */ + dwarf2_emit_insn (0); enum nds32_br_range range_type; - range_type = get_range_type (fld); pexp = insn.info; + range_type = get_range_type (fld); - out = frag_var (rs_machine_dependent, - NDS32_MAXCHAR, + out = frag_var (rs_machine_dependent, NDS32_MAXCHAR, 0, /* VAR is un-used. */ range_type, /* SUBTYPE is used as range type. */ - pexp->X_add_symbol, - pexp->X_add_number, - 0); - /* If the original frag is full, the instruction must save in next - one. */ - while (fragp->fr_next != frag_now) - fragp = fragp->fr_next; - fragp->fr_fix += insn.opcode->isize; - fragp->tc_frag_data.opcode = insn.opcode; - fragp->tc_frag_data.insn = insn.insn; - dwarf2_emit_insn (insn.opcode->isize); + pexp->X_add_symbol, pexp->X_add_number, 0); + + fragP->fr_fix += insn.opcode->isize; + fragP->tc_frag_data.opcode = insn.opcode; + fragP->tc_frag_data.insn = insn.insn; if (insn.opcode->isize == 4) bfd_putb32 (insn.insn, out); else if (insn.opcode->isize == 2) bfd_putb16 (insn.insn, out); + fragP->tc_frag_data.flag |= NDS32_FRAG_BRANCH; return; /* md_convert_frag will insert relocations. */ } - else if (!verbatim && !fld && (optimize || optimize_for_space)) - { - /* User assembly code without relocating convert it to 16bits if needed. */ - insn_32 = insn.insn; + else if (!fld && !relaxing && enable_16bit && (optimize || optimize_for_space) + && ((!verbatim && insn.opcode->isize == 4 + && nds32_convert_32_to_16 (stdoutput, insn.insn, &insn_16, NULL)) + || (insn.opcode->isize == 2 + && nds32_convert_16_to_32 (stdoutput, insn.insn, NULL)))) + { + /* Record this one is relaxable. */ + dwarf2_emit_insn (0); + out = frag_var (rs_machine_dependent, + 4, /* Max size is 32-bit instruction. */ + 0, /* VAR is un-used. */ + 0, NULL, 0, NULL); + fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE; + fragP->tc_frag_data.opcode = insn.opcode; + fragP->tc_frag_data.insn = insn.insn; + fragP->fr_fix += 2; + + /* In original, we don't relax the instrucion with label on it, + but this may cause some redundant nop16. Therefore, tag this + relaxable instruction and relax it carefully. */ + if (label) + fragP->tc_frag_data.flag |= NDS32_FRAG_LABEL; - /* Convert instruction to 16-bits. */ - if (insn.opcode->isize == 4 - && nds32_convert_32_to_16 (stdoutput, insn_32, - &insn_16, &insn_type)) + if (insn.opcode->isize == 4) + bfd_putb16 (insn_16, out); + else if (insn.opcode->isize == 2) + bfd_putb16 (insn.insn, out); + return; + } + else if ((verbatim || !relaxing) && optimize && label) + { + /* This instruction is with label. */ + expressionS exp; + out = frag_var (rs_machine_dependent, insn.opcode->isize, + 0, 0, NULL, 0, NULL); + /* If this insturction is branch target, it is not relaxable. */ + fragP->tc_frag_data.flag = NDS32_FRAG_LABEL; + fragP->tc_frag_data.opcode = insn.opcode; + fragP->tc_frag_data.insn = insn.insn; + fragP->fr_fix += insn.opcode->isize; + if (insn.opcode->isize == 4) { - out = frag_more (2); - frag_var (rs_fill, 0, 0, 0, NULL, 0, NULL); - bfd_putb16 (insn_16, out); - dwarf2_emit_insn (2); - return; + exp.X_op = O_symbol; + exp.X_add_symbol = abs_section_sym; + exp.X_add_number = 0; + fixP = fix_new_exp (fragP, 0, 0, &exp, 0, BFD_RELOC_NDS32_LABEL); } } - - out = frag_more (insn.opcode->isize); + else + out = frag_more (insn.opcode->isize); if (insn.opcode->isize == 4) bfd_putb32 (insn.insn, out); - else if (insn.opcode->isize == 2) + if (insn.opcode->isize == 2) bfd_putb16 (insn.insn, out); dwarf2_emit_insn (insn.opcode->isize); - if (fld) - { - /* Compiler generating code and user assembly pseudo load-store, insert - fixup here. */ - pexp = insn.info; - nds32_elf_record_fixup_exp (str, fld, pexp, out, &insn); - } + /* Compiler generating code and user assembly pseudo load-store, insert + fixup here. */ + pexp = insn.info; + fixP = nds32_elf_record_fixup_exp (fragP, str, fld, pexp, out, &insn); + /* Build relaxation pattern when relaxing is enable. */ + if (relaxing) + nds32_elf_build_relax_relation (fixP, pexp, out, insn.opcode, fragP, fld); } /* md_macro_start */ @@ -4933,10 +5438,17 @@ nds32_elf_get_set_cond (relax_info_t *relax_info, int offset, uint32_t *insn, int i = 0; /* The instruction has conditions. Collect condition values. */ - while (offset == code_seq_cond[i].offset) + while (code_seq_cond[i].bitmask != 0) { - mask = (ori_insn >> cond_fields[i].bitpos) & cond_fields[i].bitmask; - *insn |= (mask & code_seq_cond[i].bitmask) << code_seq_cond[i].bitpos; + if (offset == code_seq_cond[i].offset) + { + mask = (ori_insn >> cond_fields[i].bitpos) & cond_fields[i].bitmask; + /* Sign extend. */ + if (cond_fields[i].signed_extend) + mask = (mask ^ ((cond_fields[i].bitmask + 1) >> 1)) - + ((cond_fields[i].bitmask + 1) >> 1); + *insn |= (mask & code_seq_cond[i].bitmask) << code_seq_cond[i].bitpos; + } i++; } } @@ -4959,8 +5471,6 @@ nds32_relax_branch_instructions (segT segment, fragS *fragP, uint32_t *code_seq; uint32_t insn; int insn_size; - uint16_t insn_16; - int insn_type; int code_seq_offset; /* Replace with gas_assert (fragP->fr_symbol != NULL); */ @@ -5023,18 +5533,6 @@ nds32_relax_branch_instructions (segT segment, fragS *fragP, while (relax_info->relax_fixup[i][k].size !=0 && relax_info->relax_fixup[i][k].offset < code_seq_offset) k++; - if (relax_info->relax_fixup[i][k].size !=0 - && relax_info->relax_fixup[i][k].ramp & NDS32_ORIGIN) - { - /* Set register num to insntruction. */ - nds32_elf_get_set_cond (relax_info, code_seq_offset, &insn, - fragP->tc_frag_data.insn, i); - - /* Try to convert to 16-bits instruction. */ - if (nds32_convert_32_to_16 (stdoutput, - insn, &insn_16, &insn_type)) - diff -= 2; - } } code_seq_offset += insn_size; @@ -5050,6 +5548,89 @@ nds32_relax_branch_instructions (segT segment, fragS *fragP, return diff + adjust; } +/* Adjust relaxable frag till current frag. */ + +static int +nds32_adjust_relaxable_frag (fragS *startP, fragS *fragP) +{ + int adj; + if (startP->tc_frag_data.flag & NDS32_FRAG_RELAXED) + adj = -2; + else + adj = 2; + + startP->tc_frag_data.flag ^= NDS32_FRAG_RELAXED; + + while (startP) + { + startP = startP->fr_next; + if (startP) + { + startP->fr_address += adj; + if (startP == fragP) + break; + } + } + return adj; +} + +static addressT +nds32_get_align (addressT address, int align) +{ + addressT mask, new_address; + + mask = ~((~0) << align); + new_address = (address + mask) & (~mask); + return (new_address - address); +} + +/* Check the prev_frag is legal. */ +static void +invalid_prev_frag (fragS * fragP, fragS **prev_frag) +{ + addressT address; + fragS *frag_start = *prev_frag; + + if (!frag_start) + return; + + if (frag_start->last_fr_address >= fragP->last_fr_address) + { + *prev_frag = NULL; + return; + } + + fragS *frag_t = *prev_frag; + while (frag_t != fragP) + { + if (frag_t->fr_type == rs_align + || frag_t->fr_type == rs_align_code + || frag_t->fr_type == rs_align_test) + { + /* Relax instruction can not walk across lable. */ + if (frag_t->tc_frag_data.flag & NDS32_FRAG_LABEL) + { + prev_frag = NULL; + return; + } + /* Relax previos relaxable to align rs_align frag. */ + address = frag_t->fr_address + frag_t->fr_fix; + addressT offset = nds32_get_align (address, (int) frag_t->fr_offset); + if (offset & 0x2) + { + /* If there is label on the prev_frag, check if it is aligned. */ + if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL) + || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 ) + & 0x2) == 0) + nds32_adjust_relaxable_frag (*prev_frag, frag_t); + } + *prev_frag = NULL; + return; + } + frag_t = frag_t->fr_next; + } +} + /* md_relax_frag */ int @@ -5059,9 +5640,21 @@ nds32_relax_frag (segT segment, fragS *fragP, long stretch ATTRIBUTE_UNUSED) 1. relax for branch 2. relax for 32-bits to 16-bits */ - int adjust; + static fragS *prev_frag = NULL; + int adjust = 0; + + invalid_prev_frag (fragP, &prev_frag); - adjust = nds32_relax_branch_instructions (segment, fragP, stretch, 0); + if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH) + adjust = nds32_relax_branch_instructions (segment, fragP, stretch, 0); + if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL) + prev_frag = NULL; + if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE + && (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) == 0) + /* Here is considered relaxed case originally. But it may cause + unendless loop when relaxing. Once the instruction is relaxed, + it can not be undo. */ + prev_frag = fragP; return adjust; } @@ -5083,9 +5676,20 @@ md_estimate_size_before_relax (fragS *fragP, segT segment) 1. relax for branch 2. relax for 32-bits to 16-bits */ - int adjust; + /* Save previos relaxable frag. */ + static fragS *prev_frag = NULL; + int adjust = 0; + + invalid_prev_frag (fragP, &prev_frag); - adjust = nds32_relax_branch_instructions (segment, fragP, 0, 1); + if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH) + adjust = nds32_relax_branch_instructions (segment, fragP, 0, 1); + if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL) + prev_frag = NULL; + if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) + adjust = 2; + else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE) + prev_frag = fragP; return adjust; } @@ -5115,26 +5719,21 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP) char *fr_buffer; int fr_where; int addend ATTRIBUTE_UNUSED; - offsetT branch_target_address; - offsetT branch_insn_address; + offsetT branch_target_address, branch_insn_address; expressionS exp; fixS *fixP; uint32_t *code_seq; - int code_size; uint32_t insn; - int insn_size; - int offset; - int i, j, k; - uint16_t insn_16; - int insn_type; + int code_size, insn_size, offset, fixup_size; int buf_offset; - nds32_relax_fixup_info_t fixup_info[MAX_RELAX_NUM]; + int i, k; + uint16_t insn_16; + nds32_relax_fixup_info_t fixup_info[MAX_RELAX_FIX]; /* Save the 1st instruction is converted to 16 bit or not. */ - bfd_boolean insn_convert = FALSE; - int fixup_size; + unsigned int branch_size; /* Replace with gas_assert (branch_symbol != NULL); */ - if (branch_symbol == NULL) + if (branch_symbol == NULL && !(fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)) return; /* If frag_var is not enough room, the previos frag is fr_full and with @@ -5142,142 +5741,150 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP) if (opcode == NULL) return; - relax_info = hash_find (nds32_relax_info_hash, opcode->opcode); - - if (relax_info == NULL) - return; - - backup_endian = target_big_endian; - target_big_endian = 1; - - fr_where = fragP->fr_fix - opcode->isize; - fr_buffer = fragP->fr_literal + fr_where; - - if ((S_GET_SEGMENT (branch_symbol) != sec) - || S_IS_WEAK (branch_symbol)) + /* Relax the insntruction. */ + if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) { - if (fragP->fr_offset & 3) - as_warn (_("Addend to unresolved symbol is not on word boundary.")); - addend = 0; + expressionS exp_t; + if (fragP->tc_frag_data.opcode->isize == 2) + { + insn_16 = fragP->tc_frag_data.insn; + nds32_convert_16_to_32 (stdoutput, insn_16, &insn); + } + else + insn = fragP->tc_frag_data.insn; + fragP->fr_fix += 2; + fr_where = fragP->fr_fix - 4; + fr_buffer = fragP->fr_literal + fr_where; + exp_t.X_op = O_symbol; + exp_t.X_add_symbol = abs_section_sym; + exp_t.X_add_number = 0; + fix_new_exp (fragP, fr_where, 4, &exp_t, 0, + BFD_RELOC_NDS32_INSN16); + number_to_chars_bigendian (fr_buffer, insn, 4); } else { - /* Calculate symbol-to-instruction offset. */ - branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset; - branch_insn_address = fragP->fr_address + fr_where; - addend = (branch_target_address - branch_insn_address) >> 1; - } + /* Branch instruction adjust and append relocations. */ + relax_info = hash_find (nds32_relax_info_hash, opcode->opcode); - code_size = relax_info->relax_code_size[branch_range_type]; - code_seq = relax_info->relax_code_seq[branch_range_type]; + if (relax_info == NULL) + return; - memcpy (fixup_info, - relax_info->relax_fixup[branch_range_type], - sizeof (fixup_info)); + backup_endian = target_big_endian; + target_big_endian = 1; - /* Fill in frag. */ - i = 0; - k = 0; - offset = 0; /* code_seq offset */ - buf_offset = 0; /* fr_buffer offset */ - while (offset < code_size) - { - insn = code_seq[i]; - if (insn & 0x80000000) /* 16-bits instruction. */ + fr_where = fragP->fr_fix - opcode->isize; + fr_buffer = fragP->fr_literal + fr_where; + + if ((S_GET_SEGMENT (branch_symbol) != sec) + || S_IS_WEAK (branch_symbol)) { - insn = (insn >> 16) & 0xFFFF; - insn_size = 2; + if (fragP->fr_offset & 3) + as_warn (_("Addend to unresolved symbol is not on word boundary.")); + addend = 0; } - else /* 32-bits instruction. */ + else { - insn_size = 4; + /* Calculate symbol-to-instruction offset. */ + branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset; + branch_insn_address = fragP->fr_address + fr_where; + addend = (branch_target_address - branch_insn_address) >> 1; } - nds32_elf_get_set_cond (relax_info, offset, &insn, - origin_insn, branch_range_type); + code_size = relax_info->relax_code_size[branch_range_type]; + code_seq = relax_info->relax_code_seq[branch_range_type]; - /* Try to convert to 16-bits instruction. Currently, only the first - insntruction in pattern can be converted. EX: bnez sethi ori jr, - only bnez can be converted to 16 bit and ori can't. */ + memcpy (fixup_info, relax_info->relax_fixup[branch_range_type], + sizeof (fixup_info)); - while (fixup_info[k].size != 0 - && relax_info->relax_fixup[branch_range_type][k].offset < offset) - k++; - if ((fixup_info[k].size != 0 - && fixup_info[k].ramp & NDS32_ORIGIN) - && nds32_convert_32_to_16 (stdoutput, insn, &insn_16, &insn_type)) + /* Fill in frag. */ + i = 0; + k = 0; + offset = 0; /* code_seq offset */ + buf_offset = 0; /* fr_buffer offset */ + while (offset < code_size) { - /* Reduce to 16-bits instructions, adjust fixup_info[j]->offset. */ - for (j = 0; fixup_info[j].size != 0; j++) + insn = code_seq[i]; + if (insn & 0x80000000) /* 16-bits instruction. */ { - if (fixup_info[j].ramp & NDS32_RELAX) - fixup_info[j].size -= 2; - - if (fixup_info[j].offset > buf_offset) - fixup_info[j].offset -= 2; + insn = (insn >> 16) & 0xFFFF; + insn_size = 2; + } + else /* 32-bits instruction. */ + { + insn_size = 4; } - md_number_to_chars (fr_buffer + buf_offset, insn_16, 2); - buf_offset += 2; - if (offset == 0) - insn_convert = TRUE; - } - else - { - md_number_to_chars (fr_buffer + buf_offset, insn, insn_size); - buf_offset += insn_size; - } - - offset += insn_size; - i++; - } + nds32_elf_get_set_cond (relax_info, offset, &insn, + origin_insn, branch_range_type); - /* Set up fixup. */ - exp.X_op = O_symbol; + /* Try to convert to 16-bits instruction. Currently, only the first + insntruction in pattern can be converted. EX: bnez sethi ori jr, + only bnez can be converted to 16 bit and ori can't. */ - for (i = 0; fixup_info[i].size != 0; i++) - { - fixup_size = fixup_info[i].size; + while (fixup_info[k].size != 0 + && relax_info->relax_fixup[branch_range_type][k].offset < offset) + k++; - if (((fixup_info[i].ramp & NDS32_ORIGIN) && insn_convert == TRUE) - ||((fixup_info[i].ramp & NDS32_CONVERT) && insn_convert == FALSE)) - continue; + md_number_to_chars (fr_buffer + buf_offset, insn, insn_size); + buf_offset += insn_size; - if ((fixup_info[i].ramp & NDS32_CREATE_LABLE) != 0) - { - /* This is a reverse branch. */ - exp.X_add_symbol = symbol_temp_new (sec, 0, fragP->fr_next); - exp.X_add_number = 0; - } - else if ((fixup_info[i].ramp & NDS32_RELAX) != 0) - { - /* This is a relax relocation. */ - exp.X_add_symbol = abs_section_sym; - exp.X_add_number = - SET_ADDEND (fixup_size /* size */ , - insn_convert , optimize, enable_16bit); - } - else - { - exp.X_add_symbol = branch_symbol; - exp.X_add_number = branch_offset; + offset += insn_size; + i++; } - if (fixup_info[i].r_type != 0) + /* Set up fixup. */ + exp.X_op = O_symbol; + + for (i = 0; fixup_info[i].size != 0; i++) { - fixP = fix_new_exp (fragP, - fr_where + fixup_info[i].offset, - fixup_size, - &exp, - 0, - fixup_info[i].r_type); - fixP->fx_addnumber = fixP->fx_offset; + fixup_size = fixup_info[i].size; + + if ((fixup_info[i].ramp & NDS32_CREATE_LABEL) != 0) + { + /* This is a reverse branch. */ + exp.X_add_symbol = symbol_temp_new (sec, 0, fragP->fr_next); + exp.X_add_number = 0; + } + else if ((fixup_info[i].ramp & NDS32_PTR) != 0) + { + /* This relocation has to point to another instruction. */ + branch_size = fr_where + code_size - 4; + exp.X_add_symbol = symbol_temp_new (sec, branch_size, fragP); + exp.X_add_number = 0; + } + else if ((fixup_info[i].ramp & NDS32_ABS) != 0) + { + /* This is a tag relocation. */ + exp.X_add_symbol = abs_section_sym; + exp.X_add_number = 0; + } + else if ((fixup_info[i].ramp & NDS32_INSN16) != 0) + { + if (!enable_16bit) + continue; + /* This is a tag relocation. */ + exp.X_add_symbol = abs_section_sym; + exp.X_add_number = 0; + } + else + { + exp.X_add_symbol = branch_symbol; + exp.X_add_number = branch_offset; + } + + if (fixup_info[i].r_type != 0) + { + fixP = fix_new_exp (fragP, fr_where + fixup_info[i].offset, + fixup_size, &exp, 0, fixup_info[i].r_type); + fixP->fx_addnumber = fixP->fx_offset; + } } - } - fragP->fr_fix = fr_where + buf_offset; + fragP->fr_fix = fr_where + buf_offset; - target_big_endian = backup_endian; + target_big_endian = backup_endian; + } } /* tc_frob_file_before_fix */ @@ -5287,15 +5894,62 @@ nds32_frob_file_before_fix (void) { } -/* TC_FORCE_RELOCATION */ - -int -nds32_force_relocation (fixS *fix ATTRIBUTE_UNUSED) +static bfd_boolean +nds32_relaxable_section (asection *sec) { - /* Always force relocation, because linker may adjust the code. */ - return 1; + return ((sec->flags & SEC_DEBUGGING) == 0 + && strcmp (sec->name, ".eh_frame") != 0); } +/* TC_FORCE_RELOCATION */ +int +nds32_force_relocation (fixS * fix) +{ + switch (fix->fx_r_type) + { + case BFD_RELOC_NDS32_INSN16: + case BFD_RELOC_NDS32_LABEL: + case BFD_RELOC_NDS32_LONGCALL1: + case BFD_RELOC_NDS32_LONGCALL2: + case BFD_RELOC_NDS32_LONGCALL3: + case BFD_RELOC_NDS32_LONGJUMP1: + case BFD_RELOC_NDS32_LONGJUMP2: + case BFD_RELOC_NDS32_LONGJUMP3: + case BFD_RELOC_NDS32_LOADSTORE: + case BFD_RELOC_NDS32_9_FIXED: + case BFD_RELOC_NDS32_15_FIXED: + case BFD_RELOC_NDS32_17_FIXED: + case BFD_RELOC_NDS32_25_FIXED: + case BFD_RELOC_NDS32_9_PCREL: + case BFD_RELOC_NDS32_15_PCREL: + case BFD_RELOC_NDS32_17_PCREL: + case BFD_RELOC_NDS32_WORD_9_PCREL: + case BFD_RELOC_NDS32_10_UPCREL: + case BFD_RELOC_NDS32_25_PCREL: + case BFD_RELOC_NDS32_MINUEND: + case BFD_RELOC_NDS32_SUBTRAHEND: + return 1; + + case BFD_RELOC_8: + case BFD_RELOC_16: + case BFD_RELOC_32: + case BFD_RELOC_NDS32_DIFF_ULEB128: + /* Linker should handle difference between two symbol. */ + return fix->fx_subsy != NULL + && nds32_relaxable_section (S_GET_SEGMENT (fix->fx_addsy)); + case BFD_RELOC_64: + if (fix->fx_subsy) + as_bad ("Double word for difference between two symbols " + "is not supported across relaxation."); + default: + ; + } + + if (generic_force_reloc (fix)) + return 1; + + return fix->fx_pcrel; +} /* TC_VALIDATE_FIX_SUB */ @@ -5446,7 +6100,7 @@ nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, fixS *fixp; seginfo = seg_info (sec); - if (!seginfo || !symbol_rootP || !subseg_text_p (sec)) + if (!seginfo || !symbol_rootP || !subseg_text_p (sec) || sec->size == 0) return; /* If there is no relocation and relax is disabled, it is not necessary to insert R_NDS32_RELAX_ENTRY for linker do EX9 or IFC optimization. */ @@ -5547,8 +6201,8 @@ nds32_set_section_relocs (asection *sec, arelent ** relocs ATTRIBUTE_UNUSED, { bfd *abfd ATTRIBUTE_UNUSED = sec->owner; if (bfd_get_section_flags (abfd, sec) & (flagword) SEC_RELOC) - nds32_insertion_sort (sec->orelocation, sec->reloc_count, sizeof (arelent**), - compar_relent); + nds32_insertion_sort (sec->orelocation, sec->reloc_count, + sizeof (arelent**), compar_relent); } long @@ -5573,8 +6227,6 @@ nds32_post_relax_hook (void) bfd_map_over_sections (stdoutput, nds32_insert_relax_entry, NULL); } - - /* tc_fix_adjustable () Return whether this symbol (fixup) can be replaced with @@ -5596,6 +6248,13 @@ nds32_fix_adjustable (fixS *fixP) case BFD_RELOC_16: case BFD_RELOC_32: case BFD_RELOC_NDS32_PTR: + case BFD_RELOC_NDS32_LONGCALL4: + case BFD_RELOC_NDS32_LONGCALL5: + case BFD_RELOC_NDS32_LONGCALL6: + case BFD_RELOC_NDS32_LONGJUMP4: + case BFD_RELOC_NDS32_LONGJUMP5: + case BFD_RELOC_NDS32_LONGJUMP6: + case BFD_RELOC_NDS32_LONGJUMP7: return 1; default: return 0; @@ -5607,13 +6266,14 @@ nds32_fix_adjustable (fixS *fixP) void elf_nds32_final_processing (void) { - /* An FPU_COM instruction is found without previous non-FPU_COM instruction. */ + /* An FPU_COM instruction is found without previous non-FPU_COM + instruction. */ if (nds32_fpu_com && !(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST))) { /* Since only FPU_COM instructions are used and no other FPU instructions - are used. The nds32_elf_flags will be decided by the enabled options by - command line or default configuration. */ + are used. The nds32_elf_flags will be decided by the enabled options + by command line or default configuration. */ if (nds32_fpu_dp_ext || nds32_fpu_sp_ext) { nds32_elf_flags |= nds32_fpu_dp_ext ? E_NDS32_HAS_FPU_DP_INST : 0; @@ -5658,21 +6318,37 @@ nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) && fixP->fx_r_type > BFD_RELOC_NONE && fixP->fx_r_type != BFD_RELOC_NDS32_DIFF_ULEB128) { - /* FIXME: This implementation is partially borrowed from our old - nds32 binutils. Its purpose is to leave original bfd - relocation untouched, while other relocation created by CGEN - will be converted into general bfd relocations. - However, since we no longer use CGEN, we can simply use - a little piece of code to deal with general bfd relocation, - especially for the BFD_RELOC_NDS32_DATA, which is just used - as a marker for different purpose. - It is believed that we can construct a better mechanism to - deal with the whole relocation issue in nds32 target - without using CGEN. */ + /* In our old nds32 binutils, it must convert relocations which is + generated by CGEN. However, it does not have to consider this anymore. + In current, it only deal with data relocations which enum + is smaller than BFD_RELOC_NONE and BFD_RELOC_NDS32_DIFF_ULEB128. + It is believed that we can construct a better mechanism to + deal with the whole relocation issue in nds32 target + without using CGEN. */ fixP->fx_addnumber = value; fixP->tc_fix_data = NULL; - if (fixP->fx_r_type == BFD_RELOC_NDS32_DATA) - fixP->fx_done = 1; + + /* Tranform specific relocations here for later relocation generation. + Tag data here for ex9 relaxtion and tag tls data for linker. */ + switch (fixP->fx_r_type) + { + case BFD_RELOC_NDS32_DATA: + if (!enable_relax_ex9) + fixP->fx_done = 1; + break; + case BFD_RELOC_NDS32_TPOFF: + case BFD_RELOC_NDS32_TLS_LE_HI20: + case BFD_RELOC_NDS32_TLS_LE_LO12: + case BFD_RELOC_NDS32_TLS_LE_ADD: + case BFD_RELOC_NDS32_TLS_LE_LS: + case BFD_RELOC_NDS32_GOTTPOFF: + case BFD_RELOC_NDS32_TLS_IE_HI20: + case BFD_RELOC_NDS32_TLS_IE_LO12S2: + S_SET_THREAD_LOCAL (fixP->fx_addsy); + break; + default: + break; + } return; } @@ -5772,7 +6448,8 @@ nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) /* cvt_frag_to_fill () has called output_leb128 () for us. */ break; default: - as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex")); + as_bad_where (fixP->fx_file, fixP->fx_line, + _("expression too complex")); return; } } @@ -5796,7 +6473,8 @@ nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) default: as_bad_where (fixP->fx_file, fixP->fx_line, _("Internal error: Unknown fixup type %d (`%s')"), - fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type)); + fixP->fx_r_type, + bfd_get_reloc_code_name (fixP->fx_r_type)); break; } } @@ -5847,6 +6525,15 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP) return reloc; } +struct suffix_name suffix_table[] = +{ + {"GOTOFF", BFD_RELOC_NDS32_GOTOFF, 1}, + {"GOT", BFD_RELOC_NDS32_GOT20, 1}, + {"TPOFF", BFD_RELOC_NDS32_TPOFF, 0}, + {"PLT", BFD_RELOC_NDS32_25_PLTREL, 1}, + {"GOTTPOFF", BFD_RELOC_NDS32_GOTTPOFF, 0} +}; + /* Implement md_parse_name. */ int @@ -5854,35 +6541,32 @@ nds32_parse_name (char const *name, expressionS *exprP, enum expr_mode mode ATTRIBUTE_UNUSED, char *nextcharP ATTRIBUTE_UNUSED) { - char *suffix_table[] = { "GOTOFF", "GOT", "PLT" }; - short unsigned int reloc_table [] = - { - BFD_RELOC_NDS32_GOTOFF, BFD_RELOC_NDS32_GOT20, - BFD_RELOC_NDS32_25_PLTREL - }; - segT segment; - exprP->X_op_symbol = NULL; exprP->X_md = BFD_RELOC_UNUSED; exprP->X_add_symbol = symbol_find_or_make (name); + exprP->X_op = O_symbol; + exprP->X_add_number = 0; - segment = S_GET_SEGMENT (exprP->X_add_symbol); - if (segment != undefined_section) - return 0; - - if (*nextcharP == '@') + if (strcmp (name, GOT_NAME) == 0 && *nextcharP != '@') + { + /* Set for _GOT_OFFSET_TABLE_. */ + exprP->X_md = BFD_RELOC_NDS32_GOTPC20; + } + else if (*nextcharP == '@') { size_t i; char *next; for (i = 0; i < ARRAY_SIZE (suffix_table); i++) { - next = input_line_pointer + 1 + strlen (suffix_table[i]); - if (strncasecmp (input_line_pointer + 1, suffix_table[i], - strlen (suffix_table[i])) == 0 + next = input_line_pointer + 1 + strlen(suffix_table[i].suffix); + if (strncasecmp (input_line_pointer + 1, suffix_table[i].suffix, + strlen (suffix_table[i].suffix)) == 0 && !is_part_of_name (*next)) { - exprP->X_md = reloc_table[i]; + if (!nds32_pic && suffix_table[i].pic) + as_bad (_("need PIC qualifier with symbol.")); + exprP->X_md = suffix_table[i].reloc; *input_line_pointer = *nextcharP; input_line_pointer = next; *nextcharP = *input_line_pointer; @@ -5891,10 +6575,6 @@ nds32_parse_name (char const *name, expressionS *exprP, } } } - - exprP->X_op = O_symbol; - exprP->X_add_number = 0; - return 1; } @@ -5903,18 +6583,18 @@ nds32_parse_name (char const *name, expressionS *exprP, int tc_nds32_regname_to_dw2regnum (char *regname) { - symbolS *sym = symbol_find (regname); + struct nds32_keyword *sym = hash_find (nds32_gprs_hash, regname); + + if (!sym) + return -1; - if (S_GET_SEGMENT (sym) == reg_section - && sym->sy_value.X_add_number < 32) - return sym->sy_value.X_add_number; - return -1; + return sym->value; } void tc_nds32_frame_initial_instructions (void) { /* CIE */ - /* Default cfa is register-28/sp. */ + /* Default cfa is register-31/sp. */ cfi_add_CFA_def_cfa (31, 0); } diff --git a/gas/config/tc-nds32.h b/gas/config/tc-nds32.h index 731bb87..1483d51 100644 --- a/gas/config/tc-nds32.h +++ b/gas/config/tc-nds32.h @@ -42,10 +42,6 @@ #define TARGET_BYTES_BIG_ENDIAN 1 #endif -/* This is used to construct expressions out of @GOTOFF, @PLT and @GOT - symbols. The relocation type is stored in X_md. */ -#define O_PIC_reloc O_md1 - /* as.c. */ /* Extend GAS command line option handling capability. */ extern int nds32_parse_option (int, char *); @@ -154,6 +150,12 @@ extern void nds32_do_align (int); #define LOCAL_LABELS_FB 1 /* Permit temporary numeric labels. */ /* frags.c. */ + +#define NDS32_FRAG_RELAXABLE 0x1 +#define NDS32_FRAG_RELAXED 0x2 +#define NDS32_FRAG_BRANCH 0x4 +#define NDS32_FRAG_LABEL 0x8 + struct nds32_frag_type { relax_substateT flag; @@ -211,10 +213,16 @@ enum nds32_br_range enum nds32_ramp { - NDS32_CREATE_LABLE = 1, - NDS32_RELAX = 2, - NDS32_ORIGIN = 4, - NDS32_CONVERT = 8 + NDS32_CREATE_LABEL = 1, + NDS32_RELAX = (1 << 1), /* Obsolete in the future. */ + NDS32_ORIGIN = (1 << 2), + NDS32_INSN16 = (1 << 3), + NDS32_PTR = (1 << 4), + NDS32_ABS = (1 << 5), + NDS32_HINT = (1 << 6), + NDS32_FIX = (1 << 7), + NDS32_ADDEND = (1 << 8), + NDS32_SYM = (1 << 9) }; typedef struct nds32_relax_fixup_info @@ -231,13 +239,15 @@ typedef struct nds32_cond_field int offset; int bitpos; /* Register position. */ int bitmask; /* Number of register bits. */ + bfd_boolean signed_extend; } nds32_cond_field_t; /* The max relaxation pattern is 20-bytes including the nop. */ #define NDS32_MAXCHAR 20 /* In current, the max entend number of instruction for one pseudo instruction - is 4, but its number of relocation may be 5. */ -#define MAX_RELAX_NUM 8 + is 4, but its number of relocation may be 12. */ +#define MAX_RELAX_NUM 4 +#define MAX_RELAX_FIX 12 typedef struct nds32_relax_info { @@ -248,17 +258,24 @@ typedef struct nds32_relax_info /* Code sequences for different branch range. */ uint32_t relax_code_seq[BR_RANGE_NUM][MAX_RELAX_NUM]; nds32_cond_field_t relax_code_condition[BR_RANGE_NUM][MAX_RELAX_NUM]; - int relax_code_size[BR_RANGE_NUM]; + unsigned int relax_code_size[BR_RANGE_NUM]; int relax_branch_isize[BR_RANGE_NUM]; - nds32_relax_fixup_info_t relax_fixup[BR_RANGE_NUM][MAX_RELAX_NUM]; + nds32_relax_fixup_info_t relax_fixup[BR_RANGE_NUM][MAX_RELAX_FIX]; } relax_info_t; -/* Relocation table. */ -struct nds32_relocation_map +enum nds32_relax_hint_type +{ + NDS32_RELAX_HINT_NONE = 0, + NDS32_RELAX_HINT_LA, + NDS32_RELAX_HINT_LS +}; + +struct nds32_relax_hint_table { - unsigned int main_type; - /* Number of instructions, {relocations type, instruction type}. */ - unsigned int reloc_insn[6][6][3]; + enum nds32_relax_hint_type main_type; + unsigned int relax_code_size; + uint32_t relax_code_seq[MAX_RELAX_NUM]; + nds32_relax_fixup_info_t relax_fixup[MAX_RELAX_FIX]; }; #endif /* TC_NDS32 */ |