1 /* tc-nds32.c -- Assemble for the nds32 2 Copyright (C) 2012-2015 Free Software Foundation, Inc. 3 Contributed by Andes Technology Corporation. 4 5 This file is part of GAS, the GNU Assembler. 6 7 GAS is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 GAS is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GAS; see the file COPYING. If not, write to the Free 19 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 20 02110-1301, USA. */ 21 22 #include "as.h" 23 #include "safe-ctype.h" 24 #include "subsegs.h" 25 #include "symcat.h" 26 #include "dwarf2dbg.h" 27 #include "dw2gencfi.h" 28 #include "opcodes/nds32-asm.h" 29 #include "elf/nds32.h" 30 #include "bfd/elf32-nds32.h" 31 #include "hash.h" 32 #include "sb.h" 33 #include "macro.h" 34 #include "struc-symbol.h" 35 #include "opcode/nds32.h" 36 37 #include <stdio.h> 38 39 /* GAS definitions. */ 40 41 /* Characters which start a comment. */ 42 const char comment_chars[] = "!"; 43 /* Characters which start a comment when they appear at the start of a line. */ 44 const char line_comment_chars[] = "#!"; 45 /* Characters which separate lines (null and newline are by default). */ 46 const char line_separator_chars[] = ";"; 47 /* Characters which may be used as the exponent character 48 in a floating point number. */ 49 const char EXP_CHARS[] = "eE"; 50 /* Characters which may be used to indicate a floating point constant. */ 51 const char FLT_CHARS[] = "dDfF"; 52 53 static int enable_16bit = 1; 54 /* Save for md_assemble to distinguish if this instruction is 55 expanded from the pseudo instruction. */ 56 static bfd_boolean pseudo_opcode = FALSE; 57 static struct nds32_relocs_pattern *relocs_list = NULL; 58 /* Save instruction relation to inserting relaxation relocation. */ 59 struct nds32_relocs_pattern 60 { 61 segT seg; 62 fragS *frag; 63 frchainS *frchain; 64 symbolS *sym; 65 fixS* fixP; 66 struct nds32_opcode *opcode; 67 char *where; 68 struct nds32_relocs_pattern *next; 69 }; 70 71 /* Suffix name and relocation. */ 72 struct suffix_name 73 { 74 char *suffix; 75 short unsigned int reloc; 76 int pic; 77 }; 78 static int vec_size = 0; 79 /* If the assembly code is generated by compiler, it is supposed to have 80 ".flag verbatim" at beginning of the content. We have 81 'nds32_flag' to parse it and set this field to be non-zero. */ 82 static int verbatim = 0; 83 static struct hash_control *nds32_gprs_hash; 84 static struct hash_control *nds32_hint_hash; 85 #define TLS_REG "$r27" 86 #define GOT_NAME "_GLOBAL_OFFSET_TABLE_" 87 88 /* Generate relocation for relax or not, and the default is true. */ 89 static int enable_relax_relocs = 1; 90 /* The value will be used in RELAX_ENTRY. */ 91 static int enable_relax_ex9 = 0; 92 /* The value will be used in RELAX_ENTRY. */ 93 static int enable_relax_ifc = 0; 94 /* Save option -O for perfomance. */ 95 static int optimize = 0; 96 /* Save option -Os for code size. */ 97 static int optimize_for_space = 0; 98 /* Flag to save label exist. */ 99 static int label_exist = 0; 100 /* Flag to save state in omit_fp region. */ 101 static int in_omit_fp = 0; 102 extern struct nds32_keyword keyword_gpr[]; 103 /* Tag there is relax relocation having to link. */ 104 static bfd_boolean relaxing = FALSE; 105 106 static struct hash_control *nds32_relax_info_hash; 107 static relax_info_t relax_table[] = 108 { 109 { 110 "jal", /* opcode */ 111 BR_RANGE_S16M, /* br_range */ 112 {{0, 0, 0, FALSE}}, /* cond_field */ 113 { 114 { 115 INSN_JAL /* jal label */ 116 }, /* BR_RANGE_S256 */ 117 { 118 INSN_JAL /* jal label */ 119 }, /* BR_RANGE_S16K */ 120 { 121 INSN_JAL /* jal label */ 122 }, /* BR_RANGE_S64K */ 123 { 124 INSN_JAL /* jal label */ 125 }, /* BR_RANGE_S16M */ 126 { 127 INSN_SETHI_TA, /* sethi $ta, label */ 128 INSN_ORI_TA, /* ori $ta, $ta, label */ 129 INSN_JRAL_TA 130 }, /* BR_RANGE_U4G */ 131 }, /* relax_code_seq */ 132 { 133 {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ 134 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ 135 {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ 136 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ 137 {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ 138 }, /* relax_code_condition */ 139 {4, 4, 4, 4, 12}, /* relax_code_size */ 140 {4, 4, 4, 4, 4}, /* relax_branch_isize */ 141 { 142 { 143 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 144 {0, 0, 0, 0} 145 }, /* BR_RANGE_S256 */ 146 { 147 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 148 {0, 0, 0, 0} 149 }, /* BR_RANGE_S16K */ 150 { 151 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 152 {0, 0, 0, 0} 153 }, /* BR_RANGE_S64K */ 154 { 155 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 156 {0, 0, 0, 0} 157 }, /* BR_RANGE_S16M */ 158 { 159 {0, 4, 0, BFD_RELOC_NDS32_HI20}, 160 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL4}, 161 {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI}, 162 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 163 {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 164 {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 165 {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 166 {0, 0, 0, 0} 167 } /* BR_RANGE_U4G */ 168 } /* relax_fixup */ 169 }, 170 { 171 "bltzal", /* opcode */ 172 BR_RANGE_S64K, /* br_range */ 173 { 174 {0, 20, 0x1F, FALSE}, 175 {0, 0, 0, FALSE} 176 }, /* cond_field */ 177 { 178 { 179 INSN_BLTZAL /* bltzal $rt, label */ 180 }, /* BR_RANGE_S256 */ 181 { 182 INSN_BLTZAL /* bltzal $rt, label */ 183 }, /* BR_RANGE_S16K */ 184 { 185 INSN_BLTZAL /* bltzal $rt, label */ 186 }, /* BR_RANGE_S64K */ 187 { 188 INSN_BGEZ, /* bgez $rt, $1 */ 189 INSN_JAL /* jal label */ 190 }, /* BR_RANGE_S16M */ 191 { 192 INSN_BGEZ, /* bgez $rt, $1 */ 193 INSN_SETHI_TA, /* sethi $ta, label */ 194 INSN_ORI_TA, /* ori $ta, $ta, label */ 195 INSN_JRAL_TA /* jral $ta */ 196 } /* BR_RANGE_U4G */ 197 }, /* relax_code_seq */ 198 { 199 { 200 {0, 20, 0x1F, FALSE}, 201 {0, 0, 0, FALSE} 202 }, /* BR_RANGE_S256 */ 203 { 204 {0, 20, 0x1F, FALSE}, 205 {0, 0, 0, FALSE} 206 }, /* BR_RANGE_S16K */ 207 { 208 {0, 20, 0x1F, FALSE}, 209 {0, 0, 0, FALSE} 210 }, /* BR_RANGE_S64K */ 211 { 212 {0, 20, 0x1F, FALSE}, 213 {0, 0, 0, FALSE} 214 }, /* BR_RANGE_S16M */ 215 { 216 {0, 20, 0x1F, FALSE}, 217 {0, 0, 0, FALSE} 218 } /* BR_RANGE_U4G */ 219 }, /* relax_code_condition */ 220 {4, 4, 4, 8, 16}, /* relax_code_size */ 221 {4, 4, 4, 4, 4}, /* relax_branch_isize */ 222 { 223 { 224 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 225 {0, 0, 0, 0} 226 }, /* BR_RANGE_S256 */ 227 { 228 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 229 {0, 0, 0, 0} 230 }, /* BR_RANGE_S16K */ 231 { 232 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 233 {0, 0, 0, 0} 234 }, /* BR_RANGE_S64K */ 235 { 236 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 237 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5}, 238 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 239 {0, 0, 0, 0} 240 }, /* BR_RANGE_S16M */ 241 { 242 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 243 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6}, 244 {4, 4, 0, BFD_RELOC_NDS32_HI20}, 245 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 246 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, 247 {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 248 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 249 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 250 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 251 {0, 0, 0, 0} 252 } /* BR_RANGE_U4G */ 253 } /* relax_fixup */ 254 }, 255 { 256 "bgezal", /* opcode */ 257 BR_RANGE_S64K, /* br_range */ 258 { 259 {0, 20, 0x1F, FALSE}, 260 {0, 0, 0, FALSE} 261 }, /* cond_field */ 262 { 263 { 264 INSN_BGEZAL /* bgezal $rt, label */ 265 }, /* BR_RANGE_S256 */ 266 { 267 INSN_BGEZAL /* bgezal $rt, label */ 268 }, /* BR_RANGE_S16K */ 269 { 270 INSN_BGEZAL /* bgezal $rt, label */ 271 }, /* BR_RANGE_S64K */ 272 { 273 INSN_BLTZ, /* bltz $rt, $1 */ 274 INSN_JAL /* jal label */ 275 }, /* BR_RANGE_S16M */ 276 { 277 INSN_BLTZ, /* bltz $rt, $1 */ 278 INSN_SETHI_TA, /* sethi $ta, label */ 279 INSN_ORI_TA, /* ori $ta, $ta, label */ 280 INSN_JRAL_TA /* jral $ta */ 281 } /* BR_RANGE_U4G */ 282 }, /* relax_code_seq */ 283 { 284 { 285 {0, 20, 0x1F, FALSE}, 286 {0, 0, 0, FALSE} 287 }, /* BR_RANGE_S256 */ 288 { 289 {0, 20, 0x1F, FALSE}, 290 {0, 0, 0, FALSE} 291 }, /* BR_RANGE_S16K */ 292 { 293 {0, 20, 0x1F, FALSE}, 294 {0, 0, 0, FALSE} 295 }, /* BR_RANGE_S64K */ 296 { 297 {0, 20, 0x1F, FALSE}, 298 {0, 0, 0, FALSE} 299 }, /* BR_RANGE_S16M */ 300 { 301 {0, 20, 0x1F, FALSE}, 302 {0, 0, 0, FALSE} 303 } /* BR_RANGE_U4G */ 304 }, /* relax_code_condition */ 305 {4, 4, 4, 8, 16}, /* relax_code_size */ 306 {4, 4, 4, 4, 4}, /* relax_branch_isize */ 307 { 308 { 309 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 310 {0, 0, 0, 0} 311 }, /* BR_RANGE_S256 */ 312 { 313 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 314 {0, 0, 0, 0} 315 }, /* BR_RANGE_S16K */ 316 { 317 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 318 {0, 0, 0, 0} 319 }, /* BR_RANGE_S64K */ 320 { 321 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 322 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5}, 323 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 324 {0, 0, 0, 0} 325 }, /* BR_RANGE_S16M */ 326 { 327 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 328 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6}, 329 {4, 4, 0, BFD_RELOC_NDS32_HI20}, 330 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 331 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, 332 {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 333 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 334 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 335 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 336 {0, 0, 0, 0} 337 } /* BR_RANGE_U4G */ 338 } /* relax_fixup */ 339 }, 340 { 341 "j", /* opcode */ 342 BR_RANGE_S16M, /* br_range */ 343 {{0, 0, 0, FALSE}}, /* cond_field */ 344 { 345 { 346 (INSN_J8 << 16) /* j8 label */ 347 }, /* BR_RANGE_S256 */ 348 { 349 INSN_J /* j label */ 350 }, /* BR_RANGE_S16K */ 351 { 352 INSN_J /* j label */ 353 }, /* BR_RANGE_S64K */ 354 { 355 INSN_J /* j label */ 356 }, /* BR_RANGE_S16M */ 357 { 358 INSN_SETHI_TA, /* sethi $ta, label */ 359 INSN_ORI_TA, /* ori $ta, $ta, label */ 360 INSN_JR_TA /* jr $ta */ 361 }, /* BR_RANGE_U4G */ 362 }, /* relax_code_seq */ 363 { 364 {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ 365 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ 366 {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ 367 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ 368 {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ 369 }, /* relax_code_condition */ 370 {2, 4, 4, 4, 12}, /* relax_code_size */ 371 {2, 4, 4, 4, 4}, /* relax_branch_isize */ 372 { 373 { 374 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, 375 {0, 0, 0, 0} 376 }, /* BR_RANGE_S256 */ 377 { 378 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 379 {0, 0, 0, 0} 380 }, /* BR_RANGE_S16K */ 381 { 382 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 383 {0, 0, 0, 0} 384 }, /* BR_RANGE_S64K */ 385 { 386 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 387 {0, 0, 0, 0} 388 }, /* BR_RANGE_S16M */ 389 { 390 {0, 4, 0, BFD_RELOC_NDS32_HI20}, 391 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4}, 392 {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI}, 393 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 394 {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 395 {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 396 {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 397 {0, 0, 0, 0} 398 } /* BR_RANGE_U4G */ 399 } /* relax_fixup */ 400 }, 401 { 402 "j8", /* opcode */ 403 BR_RANGE_S256, /* br_range */ 404 {{0, 0, 0, FALSE}}, /* cond_field */ 405 { 406 { 407 (INSN_J8 << 16) /* j8 label */ 408 }, /* BR_RANGE_S256 */ 409 { 410 INSN_J /* j label */ 411 }, /* BR_RANGE_S16K */ 412 { 413 INSN_J /* j label */ 414 }, /* BR_RANGE_S64K */ 415 { 416 INSN_J /* j label */ 417 }, /* BR_RANGE_S16M */ 418 { 419 INSN_SETHI_TA, /* sethi $ta, label */ 420 INSN_ORI_TA, /* ori $ta, $ta, label */ 421 INSN_JR_TA /* jr $ta */ 422 }, /* BR_RANGE_U4G */ 423 }, /* relax_code_seq */ 424 { 425 {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ 426 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ 427 {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ 428 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ 429 {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ 430 }, /* relax_code_condition */ 431 {2, 4, 4, 4, 12}, /* relax_code_size */ 432 {2, 4, 4, 4, 4}, /* relax_branch_isize */ 433 { 434 { 435 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, 436 {0, 0, 0, 0} 437 }, /* BR_RANGE_S256 */ 438 { 439 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 440 {0, 0, 0, 0} 441 }, /* BR_RANGE_S16K */ 442 { 443 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 444 {0, 0, 0, 0} 445 }, /* BR_RANGE_S64K */ 446 { 447 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 448 {0, 0, 0, 0} 449 }, /* BR_RANGE_S16M */ 450 { 451 {0, 4, 0, BFD_RELOC_NDS32_HI20}, 452 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4}, 453 {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI}, 454 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 455 {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 456 {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 457 {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 458 {0, 0, 0, 0} 459 } /* BR_RANGE_U4G */ 460 } /* relax_fixup */ 461 }, 462 { 463 "beqz", /* opcode */ 464 BR_RANGE_S64K, /* br_range */ 465 { 466 {0, 20, 0x1F, FALSE}, 467 {0, 0, 0, FALSE} 468 }, /* cond_field */ 469 { 470 { 471 INSN_BEQZ /* beqz $rt, label */ 472 }, /* BR_RANGE_S256 */ 473 { 474 INSN_BEQZ /* beqz $rt, label */ 475 }, /* BR_RANGE_S16K */ 476 { 477 INSN_BEQZ /* beqz $rt, label */ 478 }, /* BR_RANGE_S64K */ 479 { 480 INSN_BNEZ, /* bnez $rt, $1 */ 481 INSN_J /* j label */ 482 }, /* BR_RANGE_S16M */ 483 { 484 INSN_BNEZ, /* bnez $rt, $1 */ 485 INSN_SETHI_TA, /* sethi $ta, label */ 486 INSN_ORI_TA, /* ori $ta, $ta, label */ 487 INSN_JR_TA /* jr $ta */ 488 } /* BR_RANGE_U4G */ 489 }, /* relax_code_seq */ 490 { 491 { 492 {0, 20, 0x1F, FALSE}, 493 {0, 0, 0, FALSE} 494 }, /* BR_RANGE_S256 */ 495 { 496 {0, 20, 0x1F, FALSE}, 497 {0, 0, 0, FALSE} 498 }, /* BR_RANGE_S16K */ 499 { 500 {0, 20, 0x1F, FALSE}, 501 {0, 0, 0, FALSE} 502 }, /* BR_RANGE_S64K */ 503 { 504 {0, 20, 0x1F, FALSE}, 505 {0, 0, 0, FALSE} 506 }, /* BR_RANGE_S16M */ 507 { 508 {0, 20, 0x1F, FALSE}, 509 {0, 0, 0, FALSE} 510 } /* BR_RANGE_U4G */ 511 }, /* relax_code_condition */ 512 {4, 4, 4, 8, 16}, /* relax_code_size */ 513 {4, 4, 4, 4, 4}, /* relax_branch_isize */ 514 { 515 { 516 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 517 {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16}, 518 {0, 0, 0, 0} 519 }, /* BR_RANGE_S256 */ 520 { 521 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 522 {0, 0, 0, 0} 523 }, /* BR_RANGE_S16K */ 524 { 525 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 526 {0, 0, 0, 0} 527 }, /* BR_RANGE_S64K */ 528 { 529 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 530 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 531 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, 532 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 533 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 534 {0, 0, 0, 0} 535 }, /* BR_RANGE_S16M */ 536 { 537 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 538 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 539 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, 540 {4, 4, 0, BFD_RELOC_NDS32_HI20}, 541 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 542 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, 543 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, 544 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 545 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 546 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 547 {0, 0, 0, 0} 548 } /* BR_RANGE_U4G */ 549 } /* relax_fixup */ 550 }, 551 { 552 "bgez", /* opcode */ 553 BR_RANGE_S64K, /* br_range */ 554 { 555 {0, 20, 0x1F, FALSE}, 556 {0, 0, 0, FALSE} 557 }, /* cond_field */ 558 { 559 { 560 INSN_BGEZ /* bgez $rt, label */ 561 }, /* BR_RANGE_S256 */ 562 { 563 INSN_BGEZ /* bgez $rt, label */ 564 }, /* BR_RANGE_S16K */ 565 { 566 INSN_BGEZ /* bgez $rt, label */ 567 }, /* BR_RANGE_S64K */ 568 { 569 INSN_BLTZ, /* bltz $rt, $1 */ 570 INSN_J /* j label */ 571 }, /* BR_RANGE_S16M */ 572 { 573 INSN_BLTZ, /* bltz $rt, $1 */ 574 INSN_SETHI_TA, /* sethi $ta, label */ 575 INSN_ORI_TA, /* ori $ta, $ta, label */ 576 INSN_JR_TA /* jr $ta */ 577 } /* BR_RANGE_U4G */ 578 }, /* relax_code_seq */ 579 { 580 { 581 {0, 20, 0x1F, FALSE}, 582 {0, 0, 0, FALSE} 583 }, /* BR_RANGE_S256 */ 584 { 585 {0, 20, 0x1F, FALSE}, 586 {0, 0, 0, FALSE} 587 }, /* BR_RANGE_S16K */ 588 { 589 {0, 20, 0x1F, FALSE}, 590 {0, 0, 0, FALSE} 591 }, /* BR_RANGE_S64K */ 592 { 593 {0, 20, 0x1F, FALSE}, 594 {0, 0, 0, FALSE} 595 }, /* BR_RANGE_S16M */ 596 { 597 {0, 20, 0x1F, FALSE}, 598 {0, 0, 0, FALSE} 599 } /* BR_RANGE_U4G */ 600 }, /* relax_code_condition */ 601 {4, 4, 4, 8, 16}, /* relax_code_size */ 602 {4, 4, 4, 4, 4}, /* relax_branch_isize */ 603 { 604 { 605 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 606 {0, 0, 0, 0} 607 }, /* BR_RANGE_S256 */ 608 { 609 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 610 {0, 0, 0, 0} 611 }, /* BR_RANGE_S16K */ 612 { 613 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 614 {0, 0, 0, 0} 615 }, /* BR_RANGE_S64K */ 616 { 617 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 618 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, 619 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 620 {0, 0, 0, 0} 621 }, /* BR_RANGE_S16M */ 622 { 623 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 624 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, 625 {4, 4, 0, BFD_RELOC_NDS32_HI20}, 626 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 627 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, 628 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, 629 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 630 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 631 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 632 {0, 0, 0, 0} 633 } /* BR_RANGE_U4G */ 634 } /* relax_fixup */ 635 }, 636 { 637 "bnez", /* opcode */ 638 BR_RANGE_S64K, /* br_range */ 639 { 640 {0, 20, 0x1F, FALSE}, 641 {0, 0, 0, FALSE} 642 }, /* cond_field */ 643 { 644 { 645 INSN_BNEZ /* bnez $rt, label */ 646 }, /* BR_RANGE_S256 */ 647 { 648 INSN_BNEZ /* bnez $rt, label */ 649 }, /* BR_RANGE_S16K */ 650 { 651 INSN_BNEZ /* bnez $rt, label */ 652 }, /* BR_RANGE_S64K */ 653 { 654 INSN_BEQZ, /* beqz $rt, $1 */ 655 INSN_J /* j label */ 656 }, /* BR_RANGE_S16M */ 657 { 658 INSN_BEQZ, /* beqz $rt, $1 */ 659 INSN_SETHI_TA, /* sethi $ta, label */ 660 INSN_ORI_TA, /* ori $ta, $ta, label */ 661 INSN_JR_TA /* jr $ta */ 662 } /* BR_RANGE_U4G */ 663 }, /* relax_code_seq */ 664 { 665 { 666 {0, 20, 0x1F, FALSE}, 667 {0, 0, 0, FALSE} 668 }, /* BR_RANGE_S256 */ 669 { 670 {0, 20, 0x1F, FALSE}, 671 {0, 0, 0, FALSE} 672 }, /* BR_RANGE_S16K */ 673 { 674 {0, 20, 0x1F, FALSE}, 675 {0, 0, 0, FALSE} 676 }, /* BR_RANGE_S64K */ 677 { 678 {0, 20, 0x1F, FALSE}, 679 {0, 0, 0, FALSE} 680 }, /* BR_RANGE_S16M */ 681 { 682 {0, 20, 0x1F, FALSE}, 683 {0, 0, 0, FALSE} 684 } /* BR_RANGE_U4G */ 685 }, /* relax_code_condition */ 686 {4, 4, 4, 8, 16}, /* relax_code_size */ 687 {4, 4, 4, 4, 4}, /* relax_branch_isize */ 688 { 689 { 690 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 691 {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16}, 692 {0, 0, 0, 0} 693 }, /* BR_RANGE_S256 */ 694 { 695 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 696 {0, 0, 0, 0} 697 }, /* BR_RANGE_S16K */ 698 { 699 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 700 {0, 0, 0, 0} 701 }, /* BR_RANGE_S64K */ 702 { 703 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 704 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 705 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, 706 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 707 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 708 {0, 0, 0, 0} 709 }, /* BR_RANGE_S16M */ 710 { 711 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 712 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 713 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, 714 {4, 4, 0, BFD_RELOC_NDS32_HI20}, 715 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 716 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, 717 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, 718 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 719 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 720 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 721 {0, 0, 0, 0} 722 } /* BR_RANGE_U4G */ 723 } /* relax_fixup */ 724 }, 725 { 726 "bgtz", /* opcode */ 727 BR_RANGE_S64K, /* br_range */ 728 { 729 {0, 20, 0x1F, FALSE}, 730 {0, 0, 0, FALSE} 731 }, /* cond_field */ 732 { 733 { 734 INSN_BGTZ /* bgtz $rt, label */ 735 }, /* BR_RANGE_S256 */ 736 { 737 INSN_BGTZ /* bgtz $rt, label */ 738 }, /* BR_RANGE_S16K */ 739 { 740 INSN_BGTZ /* bgtz $rt, label */ 741 }, /* BR_RANGE_S64K */ 742 { 743 INSN_BLEZ, /* blez $rt, $1 */ 744 INSN_J /* j label */ 745 }, /* BR_RANGE_S16M */ 746 { 747 INSN_BLEZ, /* blez $rt, $1 */ 748 INSN_SETHI_TA, /* sethi $ta, label */ 749 INSN_ORI_TA, /* ori $ta, $ta, label */ 750 INSN_JR_TA /* jr $ta */ 751 } /* BR_RANGE_U4G */ 752 }, /* relax_code_seq */ 753 { 754 { 755 {0, 20, 0x1F, FALSE}, 756 {0, 0, 0, FALSE} 757 }, /* BR_RANGE_S256 */ 758 { 759 {0, 20, 0x1F, FALSE}, 760 {0, 0, 0, FALSE} 761 }, /* BR_RANGE_S16K */ 762 { 763 {0, 20, 0x1F, FALSE}, 764 {0, 0, 0, FALSE} 765 }, /* BR_RANGE_S64K */ 766 { 767 {0, 20, 0x1F, FALSE}, 768 {0, 0, 0, FALSE} 769 }, /* BR_RANGE_S16M */ 770 { 771 {0, 20, 0x1F, FALSE}, 772 {0, 0, 0, FALSE} 773 } /* BR_RANGE_U4G */ 774 }, /* relax_code_condition */ 775 {4, 4, 4, 8, 16}, /* relax_code_size */ 776 {4, 4, 4, 4, 4}, /* relax_branch_isize */ 777 { 778 { 779 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 780 {0, 0, 0, 0} 781 }, /* BR_RANGE_S256 */ 782 { 783 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 784 {0, 0, 0, 0} 785 }, /* BR_RANGE_S16K */ 786 { 787 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 788 {0, 0, 0, 0} 789 }, /* BR_RANGE_S64K */ 790 { 791 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 792 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, 793 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 794 {0, 0, 0, 0} 795 }, /* BR_RANGE_S16M */ 796 { 797 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 798 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, 799 {4, 4, 0, BFD_RELOC_NDS32_HI20}, 800 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 801 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, 802 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, 803 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 804 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 805 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 806 {0, 0, 0, 0} 807 } /* BR_RANGE_U4G */ 808 } /* relax_fixup */ 809 }, 810 { 811 "blez", /* opcode */ 812 BR_RANGE_S64K, /* br_range */ 813 { 814 {0, 20, 0x1F, FALSE}, 815 {0, 0, 0, FALSE} 816 }, /* cond_field */ 817 { 818 { 819 INSN_BLEZ /* blez $rt, label */ 820 }, /* BR_RANGE_S256 */ 821 { 822 INSN_BLEZ /* blez $rt, label */ 823 }, /* BR_RANGE_S16K */ 824 { 825 INSN_BLEZ /* blez $rt, label */ 826 }, /* BR_RANGE_S64K */ 827 { 828 INSN_BGTZ, /* bgtz $rt, $1 */ 829 INSN_J /* j label */ 830 }, /* BR_RANGE_S16M */ 831 { 832 INSN_BGTZ, /* bgtz $rt, $1 */ 833 INSN_SETHI_TA, /* sethi $ta, label */ 834 INSN_ORI_TA, /* ori $ta, $ta, label */ 835 INSN_JR_TA /* jr $ta */ 836 } /* BR_RANGE_U4G */ 837 }, /* relax_code_seq */ 838 { 839 { 840 {0, 20, 0x1F, FALSE}, 841 {0, 0, 0, FALSE} 842 }, /* BR_RANGE_S256 */ 843 { 844 {0, 20, 0x1F, FALSE}, 845 {0, 0, 0, FALSE} 846 }, /* BR_RANGE_S16K */ 847 { 848 {0, 20, 0x1F, FALSE}, 849 {0, 0, 0, FALSE} 850 }, /* BR_RANGE_S64K */ 851 { 852 {0, 20, 0x1F, FALSE}, 853 {0, 0, 0, FALSE} 854 }, /* BR_RANGE_S16M */ 855 { 856 {0, 20, 0x1F, FALSE}, 857 {0, 0, 0, FALSE} 858 } /* BR_RANGE_U4G */ 859 }, /* relax_code_condition */ 860 {4, 4, 4, 8, 16}, /* relax_code_size */ 861 {4, 4, 4, 4, 4}, /* relax_branch_isize */ 862 { 863 { 864 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 865 {0, 0, 0, 0} 866 }, /* BR_RANGE_S256 */ 867 { 868 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 869 {0, 0, 0, 0} 870 }, /* BR_RANGE_S16K */ 871 { 872 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 873 {0, 0, 0, 0} 874 }, /* BR_RANGE_S64K */ 875 { 876 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 877 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, 878 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 879 {0, 0, 0, 0} 880 }, /* BR_RANGE_S16M */ 881 { 882 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 883 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, 884 {4, 4, 0, BFD_RELOC_NDS32_HI20}, 885 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 886 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, 887 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, 888 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 889 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 890 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 891 {0, 0, 0, 0} 892 } /* BR_RANGE_U4G */ 893 } /* relax_fixup */ 894 }, 895 { 896 "bltz", /* opcode */ 897 BR_RANGE_S64K, /* br_range */ 898 { 899 {0, 20, 0x1F, FALSE}, 900 {0, 0, 0, FALSE} 901 }, /* cond_field */ 902 { 903 { 904 INSN_BLTZ /* bltz $rt, label */ 905 }, /* BR_RANGE_S256 */ 906 { 907 INSN_BLTZ /* bltz $rt, label */ 908 }, /* BR_RANGE_S16K */ 909 { 910 INSN_BLTZ /* bltz $rt, label */ 911 }, /* BR_RANGE_S64K */ 912 { 913 INSN_BGEZ, /* bgez $rt, $1 */ 914 INSN_J /* j label */ 915 }, /* BR_RANGE_S16M */ 916 { 917 INSN_BGEZ, /* bgez $rt, $1 */ 918 INSN_SETHI_TA, /* sethi $ta, label */ 919 INSN_ORI_TA, /* ori $ta, $ta, label */ 920 INSN_JR_TA /* jr $ta */ 921 } /* BR_RANGE_U4G */ 922 }, /* relax_code_seq */ 923 { 924 { 925 {0, 20, 0x1F, FALSE}, 926 {0, 0, 0, FALSE} 927 }, /* BR_RANGE_S256 */ 928 { 929 {0, 20, 0x1F, FALSE}, 930 {0, 0, 0, FALSE} 931 }, /* BR_RANGE_S16K */ 932 { 933 {0, 20, 0x1F, FALSE}, 934 {0, 0, 0, FALSE} 935 }, /* BR_RANGE_S64K */ 936 { 937 {0, 20, 0x1F, FALSE}, 938 {0, 0, 0, FALSE} 939 }, /* BR_RANGE_S16M */ 940 { 941 {0, 20, 0x1F, FALSE}, 942 {0, 0, 0, FALSE} 943 } /* BR_RANGE_U4G */ 944 }, /* relax_code_condition */ 945 {4, 4, 4, 8, 16}, /* relax_code_size */ 946 {4, 4, 4, 4, 4}, /* relax_branch_isize */ 947 { 948 { 949 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 950 {0, 0, 0, 0} 951 }, /* BR_RANGE_S256 */ 952 { 953 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 954 {0, 0, 0, 0} 955 }, /* BR_RANGE_S16K */ 956 { 957 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 958 {0, 0, 0, 0} 959 }, /* BR_RANGE_S64K */ 960 { 961 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 962 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, 963 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 964 {0, 0, 0, 0} 965 }, /* BR_RANGE_S16M */ 966 { 967 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 968 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, 969 {4, 4, 0, BFD_RELOC_NDS32_HI20}, 970 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 971 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, 972 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, 973 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 974 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 975 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 976 {0, 0, 0, 0} 977 } /* BR_RANGE_U4G */ 978 } /* relax_fixup */ 979 }, 980 { 981 "beq", /* opcode */ 982 BR_RANGE_S16K, /* br_range */ 983 { 984 {0, 20, 0x1F, FALSE}, 985 {0, 15, 0x1F, FALSE}, 986 {0, 0, 0, FALSE} 987 }, /* cond_field */ 988 { 989 { 990 INSN_BEQ /* beq $rt, $ra, label */ 991 }, /* BR_RANGE_S256 */ 992 { 993 INSN_BEQ /* beq $rt, $ra, label */ 994 }, /* BR_RANGE_S16K */ 995 { 996 INSN_BNE, /* bne $rt, $ra, $1 */ 997 INSN_J /* j label */ 998 }, /* BR_RANGE_S64K */ 999 { 1000 INSN_BNE, /* bne $rt, $ra, $1 */ 1001 INSN_J /* j label */ 1002 }, /* BR_RANGE_S16M */ 1003 { 1004 INSN_BNE, /* bne $rt, $ra, $1 */ 1005 INSN_SETHI_TA, /* sethi $ta, label */ 1006 INSN_ORI_TA, /* ori $ta, $ta, label */ 1007 INSN_JR_TA /* jr $ta */ 1008 } /* BR_RANGE_U4G */ 1009 }, /* relax_code_seq */ 1010 { 1011 { 1012 {0, 20, 0x1F, FALSE}, 1013 {0, 15, 0x1F, FALSE}, 1014 {0, 0, 0, FALSE} 1015 }, /* BR_RANGE_S256 */ 1016 { 1017 {0, 20, 0x1F, FALSE}, 1018 {0, 15, 0x1F, FALSE}, 1019 {0, 0, 0, FALSE} 1020 }, /* BR_RANGE_S16K */ 1021 { 1022 {0, 20, 0x1F, FALSE}, 1023 {0, 15, 0x1F, FALSE}, 1024 {0, 0, 0, FALSE} 1025 }, /* BR_RANGE_S64K */ 1026 { 1027 {0, 20, 0x1F, FALSE}, 1028 {0, 15, 0x1F, FALSE}, 1029 {0, 0, 0, FALSE} 1030 }, /* BR_RANGE_S16M */ 1031 { 1032 {0, 20, 0x1F, FALSE}, 1033 {0, 15, 0x1F, FALSE}, 1034 {0, 0, 0, FALSE} 1035 } /* BR_RANGE_U4G */ 1036 }, /* relax_code_condition */ 1037 {4, 4, 8, 8, 16}, /* relax_code_size */ 1038 {4, 4, 4, 4, 4}, /* relax_branch_isize */ 1039 { 1040 { 1041 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1042 {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, 1043 {0, 0, 0, 0} 1044 }, /* BR_RANGE_S256 */ 1045 { 1046 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1047 {0, 0, 0, 0} 1048 }, /* BR_RANGE_S16K */ 1049 { 1050 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1051 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1052 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, 1053 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 1054 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1055 {0, 0, 0, 0} 1056 }, /* BR_RANGE_S64K */ 1057 { 1058 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1059 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1060 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, 1061 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 1062 {4, 4, NDS32_ABS, BFD_RELOC_NDS32_EMPTY}, 1063 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1064 {0, 0, 0, 0} 1065 }, /* BR_RANGE_S16M */ 1066 { 1067 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1068 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1069 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, 1070 {4, 4, 0, BFD_RELOC_NDS32_HI20}, 1071 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 1072 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, 1073 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, 1074 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 1075 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 1076 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1077 {0, 0, 0, 0} 1078 } /* BR_RANGE_U4G */ 1079 } /* relax_fixup */ 1080 }, 1081 { 1082 "bne", /* opcode */ 1083 BR_RANGE_S16K, /* br_range */ 1084 { 1085 {0, 20, 0x1F, FALSE}, 1086 {0, 15, 0x1F, FALSE}, 1087 {0, 0, 0, FALSE} 1088 }, /* cond_field */ 1089 { 1090 { 1091 INSN_BNE /* bne $rt, $ra, label */ 1092 }, /* BR_RANGE_S256 */ 1093 { 1094 INSN_BNE /* bne $rt, $ra, label */ 1095 }, /* BR_RANGE_S16K */ 1096 { 1097 INSN_BEQ, /* beq $rt, $ra, $1 */ 1098 INSN_J /* j label */ 1099 }, /* BR_RANGE_S64K */ 1100 { 1101 INSN_BEQ, /* beq $rt, $ra, $1 */ 1102 INSN_J /* j label */ 1103 }, /* BR_RANGE_S16M */ 1104 { 1105 INSN_BEQ, /* beq $rt, $ra, $1 */ 1106 INSN_SETHI_TA, /* sethi $ta, label */ 1107 INSN_ORI_TA, /* ori $ta, $ta, label */ 1108 INSN_JR_TA /* jr $ta */ 1109 } /* BR_RANGE_U4G */ 1110 }, /* relax_code_seq */ 1111 { 1112 { 1113 {0, 20, 0x1F, FALSE}, 1114 {0, 15, 0x1F, FALSE}, 1115 {0, 0, 0, FALSE} 1116 }, /* BR_RANGE_S256 */ 1117 { 1118 {0, 20, 0x1F, FALSE}, 1119 {0, 15, 0x1F, FALSE}, 1120 {0, 0, 0, FALSE} 1121 }, /* BR_RANGE_S16K */ 1122 { 1123 {0, 20, 0x1F, FALSE}, 1124 {0, 15, 0x1F, FALSE}, 1125 {0, 0, 0, FALSE} 1126 }, /* BR_RANGE_S64K */ 1127 { 1128 {0, 20, 0x1F, FALSE}, 1129 {0, 15, 0x1F, FALSE}, 1130 {0, 0, 0, FALSE} 1131 }, /* BR_RANGE_S16M */ 1132 { 1133 {0, 20, 0x1F, FALSE}, 1134 {0, 15, 0x1F, FALSE}, 1135 {0, 0, 0, FALSE} 1136 } /* BR_RANGE_U4G */ 1137 }, /* relax_code_condition */ 1138 {4, 4, 8, 8, 16}, /* relax_code_size */ 1139 {4, 4, 4, 4, 4}, /* relax_branch_isize */ 1140 { 1141 { 1142 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1143 {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, 1144 {0, 0, 0, 0} 1145 }, /* BR_RANGE_S256 */ 1146 { 1147 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1148 {0, 0, 0, 0} 1149 }, /* BR_RANGE_S16K */ 1150 { 1151 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1152 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1153 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, 1154 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 1155 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1156 {0, 0, 0, 0} 1157 }, /* BR_RANGE_S64K */ 1158 { 1159 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1160 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1161 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, 1162 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 1163 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1164 {0, 0, 0, 0} 1165 }, /* BR_RANGE_S16M */ 1166 { 1167 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1168 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1169 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, 1170 {4, 4, 0, BFD_RELOC_NDS32_HI20}, 1171 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 1172 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, 1173 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, 1174 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 1175 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 1176 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1177 {0, 0, 0, 0} 1178 } /* BR_RANGE_U4G */ 1179 } /* relax_fixup */ 1180 }, 1181 { 1182 "beqz38", /* opcode */ 1183 BR_RANGE_S256, /* br_range */ 1184 { 1185 {0, 8, 0x7, FALSE}, 1186 {0, 0, 0, FALSE} 1187 }, /* cond_field */ 1188 { 1189 { 1190 INSN_BEQZ38 << 16 /* beqz $rt, label */ 1191 }, /* BR_RANGE_S256 */ 1192 { 1193 INSN_BEQZ /* beqz $rt, label */ 1194 }, /* BR_RANGE_S16K */ 1195 { 1196 INSN_BEQZ /* beqz $rt, label */ 1197 }, /* BR_RANGE_S64K */ 1198 { 1199 INSN_BNEZ, /* bnez $rt, $1 */ 1200 INSN_J /* j label */ 1201 }, /* BR_RANGE_S16M */ 1202 { 1203 INSN_BNEZ, /* bnez $rt, $1 */ 1204 INSN_SETHI_TA, /* sethi $ta, label */ 1205 INSN_ORI_TA, /* ori $ta, $ta, label */ 1206 INSN_JR_TA /* jr $ta */ 1207 } /* BR_RANGE_U4G */ 1208 }, /* relax_code_seq */ 1209 { 1210 { 1211 {0, 8, 0x7, FALSE}, 1212 {0, 0, 0, FALSE} 1213 }, /* BR_RANGE_S256 */ 1214 { 1215 {0, 20, 0x1F, FALSE}, 1216 {0, 0, 0, FALSE} 1217 }, /* BR_RANGE_S16K */ 1218 { 1219 {0, 20, 0x1F, FALSE}, 1220 {0, 0, 0, FALSE} 1221 }, /* BR_RANGE_S64K */ 1222 { 1223 {0, 20, 0x1F, FALSE}, 1224 {0, 0, 0, FALSE} 1225 }, /* BR_RANGE_S16M */ 1226 { 1227 {0, 20, 0x1F, FALSE}, 1228 {0, 0, 0, FALSE} 1229 } /* BR_RANGE_U4G */ 1230 }, /* relax_code_condition */ 1231 {2, 4, 4, 8, 16}, /* relax_code_size */ 1232 {2, 4, 4, 4, 4}, /* relax_branch_isize */ 1233 { 1234 { 1235 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, 1236 {0, 0, 0, 0} 1237 }, /* BR_RANGE_S256 */ 1238 { 1239 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 1240 {0, 0, 0, 0} 1241 }, /* BR_RANGE_S16K */ 1242 { 1243 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 1244 {0, 0, 0, 0} 1245 }, /* BR_RANGE_S64K */ 1246 { 1247 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1248 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1249 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, 1250 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 1251 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1252 {0, 0, 0, 0} 1253 }, /* BR_RANGE_S16M */ 1254 { 1255 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1256 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1257 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, 1258 {4, 4, 0, BFD_RELOC_NDS32_HI20}, 1259 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 1260 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, 1261 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, 1262 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 1263 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 1264 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1265 {0, 0, 0, 0} 1266 } /* BR_RANGE_U4G */ 1267 } /* relax_fixup */ 1268 }, 1269 { 1270 "bnez38", /* opcode */ 1271 BR_RANGE_S256, /* br_range */ 1272 { 1273 {0, 8, 0x7, FALSE}, 1274 {0, 0, 0, FALSE} 1275 }, /* cond_field */ 1276 { 1277 { 1278 INSN_BNEZ38 << 16 /* bnez $rt, label */ 1279 }, /* BR_RANGE_S256 */ 1280 { 1281 INSN_BNEZ /* bnez $rt, label */ 1282 }, /* BR_RANGE_S16K */ 1283 { 1284 INSN_BNEZ /* bnez $rt, label */ 1285 }, /* BR_RANGE_S64K */ 1286 { 1287 INSN_BEQZ, /* beqz $rt, $1 */ 1288 INSN_J /* j label */ 1289 }, /* BR_RANGE_S16M */ 1290 { 1291 INSN_BEQZ, /* beqz $rt, $1 */ 1292 INSN_SETHI_TA, /* sethi $ta, label */ 1293 INSN_ORI_TA, /* ori $ta, $ta, label */ 1294 INSN_JR_TA /* jr $ta */ 1295 } /* BR_RANGE_U4G */ 1296 }, /* relax_code_seq */ 1297 { 1298 { 1299 {0, 8, 0x7, FALSE}, 1300 {0, 0, 0, FALSE} 1301 }, /* BR_RANGE_S256 */ 1302 { 1303 {0, 20, 0x1F, FALSE}, 1304 {0, 0, 0, FALSE} 1305 }, /* BR_RANGE_S16K */ 1306 { 1307 {0, 20, 0x1F, FALSE}, 1308 {0, 0, 0, FALSE} 1309 }, /* BR_RANGE_S64K */ 1310 { 1311 {0, 20, 0x1F, FALSE}, 1312 {0, 0, 0, FALSE} 1313 }, /* BR_RANGE_S16M */ 1314 { 1315 {0, 20, 0x1F, FALSE}, 1316 {0, 0, 0, FALSE} 1317 } /* BR_RANGE_U4G */ 1318 }, /* relax_code_condition */ 1319 {2, 4, 4, 8, 16}, /* relax_code_size */ 1320 {2, 4, 4, 4, 4}, /* relax_branch_isize */ 1321 { 1322 { 1323 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, 1324 {0, 0, 0, 0} 1325 }, /* BR_RANGE_S256 */ 1326 { 1327 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 1328 {0, 0, 0, 0} 1329 }, /* BR_RANGE_S16K */ 1330 { 1331 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 1332 {0, 0, 0, 0} 1333 }, /* BR_RANGE_S64K */ 1334 { 1335 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1336 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1337 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, 1338 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 1339 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1340 {0, 0, 0, 0} 1341 }, /* BR_RANGE_S16M */ 1342 { 1343 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1344 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1345 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, 1346 {4, 4, 0, BFD_RELOC_NDS32_HI20}, 1347 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 1348 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, 1349 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, 1350 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 1351 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 1352 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1353 {0, 0, 0, 0} 1354 } /* BR_RANGE_U4G */ 1355 } /* relax_fixup */ 1356 }, 1357 { 1358 "beqzs8", /* opcode */ 1359 BR_RANGE_S256, /* br_range */ 1360 {{0, 0, 0, FALSE}}, /* cond_field */ 1361 { 1362 { 1363 INSN_BEQZS8 << 16 /* beqz $r15, label */ 1364 }, /* BR_RANGE_S256 */ 1365 { 1366 INSN_BEQZ_TA /* bnez $rt, label */ 1367 }, /* BR_RANGE_S16K */ 1368 { 1369 INSN_BEQZ_TA /* bnez $rt, label */ 1370 }, /* BR_RANGE_S64K */ 1371 { 1372 INSN_BNEZ_TA, /* bnez $r15, $1 */ 1373 INSN_J /* j label */ 1374 }, /* BR_RANGE_S16M */ 1375 { 1376 INSN_BNEZ_TA, /* bnez $r15, $1 */ 1377 INSN_SETHI_TA, /* sethi $ta, label */ 1378 INSN_ORI_TA, /* ori $ta, $ta, label */ 1379 INSN_JR_TA /* jr $ta */ 1380 } /* BR_RANGE_U4G */ 1381 }, /* relax_code_seq */ 1382 { 1383 {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ 1384 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ 1385 {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ 1386 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ 1387 {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ 1388 }, /* relax_code_condition */ 1389 {2, 4, 4, 8, 16}, /* relax_code_size */ 1390 {2, 4, 4, 4, 4}, /* relax_branch_isize */ 1391 { 1392 { 1393 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, 1394 {0, 0, 0, 0} 1395 }, /* BR_RANGE_S256 */ 1396 { 1397 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 1398 {0, 0, 0, 0} 1399 }, /* BR_RANGE_S16K */ 1400 { 1401 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 1402 {0, 0, 0, 0} 1403 }, /* BR_RANGE_S64K */ 1404 { 1405 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1406 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1407 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, 1408 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 1409 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1410 {0, 0, 0, 0} 1411 }, /* BR_RANGE_S16M */ 1412 { 1413 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1414 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1415 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, 1416 {4, 4, 0, BFD_RELOC_NDS32_HI20}, 1417 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 1418 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, 1419 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, 1420 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 1421 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 1422 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1423 {0, 0, 0, 0} 1424 } /* BR_RANGE_U4G */ 1425 } /* relax_fixup */ 1426 }, 1427 { 1428 "bnezs8", /* opcode */ 1429 BR_RANGE_S256, /* br_range */ 1430 {{0, 0, 0, FALSE}}, /* cond_field */ 1431 { 1432 { 1433 INSN_BNEZS8 << 16 /* bnez $r15, label */ 1434 }, /* BR_RANGE_S256 */ 1435 { 1436 INSN_BNEZ_TA /* bnez $r15, label */ 1437 }, /* BR_RANGE_S16K */ 1438 { 1439 INSN_BNEZ_TA /* bnez $r15, label */ 1440 }, /* BR_RANGE_S64K */ 1441 { 1442 INSN_BEQZ_TA, /* beqz $r15, $1 */ 1443 INSN_J /* j label */ 1444 }, /* BR_RANGE_S16M */ 1445 { 1446 INSN_BEQZ_TA, /* beqz $r15, $1 */ 1447 INSN_SETHI_TA, /* sethi $ta, label */ 1448 INSN_ORI_TA, /* ori $ta, $ta, label */ 1449 INSN_JR_TA /* jr $ta */ 1450 } /* BR_RANGE_U4G */ 1451 }, /* relax_code_seq */ 1452 { 1453 {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */ 1454 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */ 1455 {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */ 1456 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */ 1457 {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */ 1458 }, /* relax_code_condition */ 1459 {2, 4, 4, 8, 16}, /* relax_code_size */ 1460 {2, 4, 4, 4, 4}, /* relax_branch_isize */ 1461 { 1462 { 1463 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, 1464 {0, 0, 0, 0} 1465 }, /* BR_RANGE_S256 */ 1466 { 1467 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 1468 {0, 0, 0, 0} 1469 }, /* BR_RANGE_S16K */ 1470 { 1471 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL}, 1472 {0, 0, 0, 0} 1473 }, /* BR_RANGE_S64K */ 1474 { 1475 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1476 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1477 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, 1478 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 1479 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1480 {0, 0, 0, 0} 1481 }, /* BR_RANGE_S16M */ 1482 { 1483 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1484 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1485 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, 1486 {4, 4, 0, BFD_RELOC_NDS32_HI20}, 1487 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 1488 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, 1489 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, 1490 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 1491 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 1492 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1493 {0, 0, 0, 0} 1494 } /* BR_RANGE_U4G */ 1495 } /* relax_fixup */ 1496 }, 1497 { 1498 "bnes38", /* opcode */ 1499 BR_RANGE_S256, /* br_range */ 1500 { 1501 {0, 8, 0x7, FALSE}, 1502 {0, 0, 0, FALSE} 1503 }, /* cond_field */ 1504 { 1505 { 1506 INSN_BNES38 << 16 /* bne $rt, $R5, label */ 1507 }, /* BR_RANGE_S256 */ 1508 { 1509 INSN_BNE_R5 /* bne $rt, $R5, label */ 1510 }, /* BR_RANGE_S16K */ 1511 { 1512 INSN_BEQ_R5, /* beq $rt, $R5, $1 */ 1513 INSN_J /* j label */ 1514 }, /* BR_RANGE_S64K */ 1515 { 1516 INSN_BEQ_R5, /* beq $rt, $R5, $1 */ 1517 INSN_J /* j label */ 1518 }, /* BR_RANGE_S16M */ 1519 { 1520 INSN_BEQ_R5, /* beq $rt, $R5, $1 */ 1521 INSN_SETHI_TA, /* sethi $ta, label */ 1522 INSN_ORI_TA, /* ori $ta, $ta, label */ 1523 INSN_JR_TA /* jr $ta */ 1524 } /* BR_RANGE_U4G */ 1525 }, /* relax_code_seq */ 1526 { 1527 { 1528 {0, 8, 0x7, FALSE}, 1529 {0, 0, 0, FALSE} 1530 }, /* BR_RANGE_S256 */ 1531 { 1532 {0, 20, 0x1F, FALSE}, 1533 {0, 0, 0, FALSE} 1534 }, /* BR_RANGE_S16K */ 1535 { 1536 {0, 20, 0x1F, FALSE}, 1537 {0, 0, 0, FALSE} 1538 }, /* BR_RANGE_S64K */ 1539 { 1540 {0, 20, 0x1F, FALSE}, 1541 {0, 0, 0, FALSE} 1542 }, /* BR_RANGE_S16M */ 1543 { 1544 {0, 20, 0x1F, FALSE}, 1545 {0, 0, 0, FALSE} 1546 } /* BR_RANGE_U4G */ 1547 }, /* relax_code_condition */ 1548 {2, 4, 8, 8, 16}, /* relax_code_size */ 1549 {2, 4, 4, 4, 4}, /* relax_branch_isize */ 1550 { 1551 { 1552 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, 1553 {0, 0, 0, 0} 1554 }, /* BR_RANGE_S256 */ 1555 { 1556 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1557 {0, 0, 0, 0} 1558 }, /* BR_RANGE_S16K */ 1559 { 1560 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1561 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1562 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, 1563 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 1564 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1565 {0, 0, 0, 0} 1566 }, /* BR_RANGE_S64K */ 1567 { 1568 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1569 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1570 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, 1571 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 1572 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1573 {0, 0, 0, 0} 1574 }, /* BR_RANGE_S16M */ 1575 { 1576 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1577 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1578 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, 1579 {4, 4, 0, BFD_RELOC_NDS32_HI20}, 1580 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 1581 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, 1582 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, 1583 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 1584 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 1585 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1586 {0, 0, 0, 0} 1587 } /* BR_RANGE_U4G */ 1588 } /* relax_fixup */ 1589 }, 1590 { 1591 "beqs38", /* opcode */ 1592 BR_RANGE_S256, /* br_range */ 1593 { 1594 {0, 8, 0x7, FALSE}, 1595 {0, 0, 0, FALSE} 1596 }, /* cond_field */ 1597 { 1598 { 1599 INSN_BEQS38 << 16 /* beq $rt, $R5, label */ 1600 }, /* BR_RANGE_S256 */ 1601 { 1602 INSN_BEQ_R5 /* beq $rt, $R5, label */ 1603 }, /* BR_RANGE_S16K */ 1604 { 1605 INSN_BNE_R5, /* bne $rt, $R5, $1 */ 1606 INSN_J /* j label */ 1607 }, /* BR_RANGE_S64K */ 1608 { 1609 INSN_BNE_R5, /* bne $rt, $R5, $1 */ 1610 INSN_J /* j label */ 1611 }, /* BR_RANGE_S16M */ 1612 { 1613 INSN_BNE_R5, /* bne $rt, $R5, $1 */ 1614 INSN_SETHI_TA, /* sethi $ta, label */ 1615 INSN_ORI_TA, /* ori $ta, $ta, label */ 1616 INSN_JR_TA /* jr $ta */ 1617 } /* BR_RANGE_U4G */ 1618 }, /* relax_code_seq */ 1619 { 1620 { 1621 {0, 8, 0x7, FALSE}, 1622 {0, 0, 0, FALSE} 1623 }, /* BR_RANGE_S256 */ 1624 { 1625 {0, 20, 0x1F, FALSE}, 1626 {0, 0, 0, FALSE} 1627 }, /* BR_RANGE_S16K */ 1628 { 1629 {0, 20, 0x1F, FALSE}, 1630 {0, 0, 0, FALSE} 1631 }, /* BR_RANGE_S64K */ 1632 { 1633 {0, 20, 0x1F, FALSE}, 1634 {0, 0, 0, FALSE} 1635 }, /* BR_RANGE_S16M */ 1636 { 1637 {0, 20, 0x1F, FALSE}, 1638 {0, 0, 0, FALSE} 1639 } /* BR_RANGE_U4G */ 1640 }, /* relax_code_condition */ 1641 {2, 4, 8, 8, 16}, /* relax_code_size */ 1642 {2, 4, 4, 4, 4}, /* relax_branch_isize */ 1643 { 1644 { 1645 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL}, 1646 {0, 0, 0, 0} 1647 }, /* BR_RANGE_S256 */ 1648 { 1649 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1650 {0, 0, 0, 0} 1651 }, /* BR_RANGE_S16K */ 1652 { 1653 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1654 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1655 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, 1656 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 1657 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1658 {0, 0, 0, 0} 1659 }, /* BR_RANGE_S64K */ 1660 { 1661 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1662 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1663 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5}, 1664 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 1665 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1666 {0, 0, 0, 0} 1667 }, /* BR_RANGE_S16M */ 1668 { 1669 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1670 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1671 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6}, 1672 {4, 4, 0, BFD_RELOC_NDS32_HI20}, 1673 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR}, 1674 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI}, 1675 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR}, 1676 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED}, 1677 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY}, 1678 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1679 {0, 0, 0, 0} 1680 } /* BR_RANGE_U4G */ 1681 } /* relax_fixup */ 1682 }, 1683 { 1684 "beqc", /* opcode */ 1685 BR_RANGE_S256, /* br_range */ 1686 { 1687 {0, 8, 0x7FF, TRUE}, 1688 {0, 20, 0x1F, FALSE}, 1689 {0, 0, 0, FALSE} 1690 }, /* cond_field */ 1691 { 1692 { 1693 INSN_BEQC /* beqc $rt, imm11s, label */ 1694 }, /* BR_RANGE_S256 */ 1695 { 1696 INSN_MOVI_TA, /* movi $ta, imm11s */ 1697 INSN_BEQ_TA /* beq $rt, $ta, label */ 1698 }, /* BR_RANGE_S16K */ 1699 { 1700 INSN_BNEC, /* bnec $rt, imm11s, $1 */ 1701 INSN_J /* j label */ 1702 }, /* BR_RANGE_S64K */ 1703 { 1704 INSN_BNEC, /* bnec $rt, imm11s, $1 */ 1705 INSN_J /* j label */ 1706 }, /* BR_RANGE_S16M */ 1707 { 1708 INSN_BNEC, /* bnec $rt, imm11s, $1 */ 1709 INSN_SETHI_TA, /* sethi $ta, label */ 1710 INSN_ORI_TA, /* ori $ta, $ta, label */ 1711 INSN_JR_TA /* jr $ta */ 1712 } /* BR_RANGE_U4G */ 1713 }, /* relax_code_seq */ 1714 { 1715 { 1716 {0, 8, 0x7FF, TRUE}, 1717 {0, 20, 0x1F, FALSE}, 1718 {0, 0, 0, FALSE} 1719 }, /* BR_RANGE_S256 */ 1720 { 1721 {0, 0, 0xFFFFF, FALSE}, 1722 {4, 20, 0x1F, FALSE}, 1723 {0, 0, 0, FALSE} 1724 }, /* BR_RANGE_S16K */ 1725 { 1726 {0, 8, 0x7FF, FALSE}, 1727 {0, 20, 0x1F, FALSE}, 1728 {0, 0, 0, FALSE} 1729 }, /* BR_RANGE_S64K */ 1730 { 1731 {0, 8, 0x7FF, FALSE}, 1732 {0, 20, 0x1F, FALSE}, 1733 {0, 0, 0, FALSE} 1734 }, /* BR_RANGE_S16M */ 1735 { 1736 {0, 8, 0x7FF, FALSE}, 1737 {0, 20, 0x1F, FALSE}, 1738 {0, 0, 0, FALSE} 1739 } /* BR_RANGE_U4G */ 1740 }, /* relax_code_condition */ 1741 {4, 8, 8, 8, 16}, /* relax_code_size */ 1742 {4, 4, 4, 4, 4}, /* relax_branch_isize */ 1743 { 1744 { 1745 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, 1746 {0, 0, 0, 0} 1747 }, /* BR_RANGE_S256 */ 1748 { 1749 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1750 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7}, 1751 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1752 {0, 0, 0, 0} 1753 }, /* BR_RANGE_S16K */ 1754 { 1755 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, 1756 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 1757 {0, 0, 0, 0} 1758 }, /* BR_RANGE_S64K */ 1759 { 1760 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, 1761 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 1762 {0, 0, 0, 0} 1763 }, /* BR_RANGE_S16M */ 1764 { 1765 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, 1766 {4, 4, 0, BFD_RELOC_NDS32_HI20}, 1767 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, 1768 {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, 1769 {0, 0, 0, 0} 1770 } /* BR_RANGE_U4G */ 1771 } /* relax_fixup */ 1772 }, 1773 { 1774 "bnec", /* opcode */ 1775 BR_RANGE_S256, /* br_range */ 1776 { 1777 {0, 8, 0x7FF, TRUE}, 1778 {0, 20, 0x1F, FALSE}, 1779 {0, 0, 0, FALSE} 1780 }, /* cond_field */ 1781 { 1782 { 1783 INSN_BNEC /* bnec $rt, imm11s, label */ 1784 }, /* BR_RANGE_S256 */ 1785 { 1786 INSN_MOVI_TA, /* movi $ta, imm11s */ 1787 INSN_BNE_TA /* bne $rt, $ta, label */ 1788 }, /* BR_RANGE_S16K */ 1789 { 1790 INSN_BEQC, /* beqc $rt, imm11s, $1 */ 1791 INSN_J /* j label */ 1792 }, /* BR_RANGE_S64K */ 1793 { 1794 INSN_BEQC, /* beqc $rt, imm11s, $1 */ 1795 INSN_J /* j label */ 1796 }, /* BR_RANGE_S16M */ 1797 { 1798 INSN_BEQC, /* beqc $rt, imm11s, $1 */ 1799 INSN_SETHI_TA, /* sethi $ta, label */ 1800 INSN_ORI_TA, /* ori $ta, $ta, label */ 1801 INSN_JR_TA /* jr $ta */ 1802 } /* BR_RANGE_U4G */ 1803 }, /* relax_code_seq */ 1804 { 1805 { 1806 {0, 8, 0x7FF, TRUE}, 1807 {0, 20, 0x1F, FALSE}, 1808 {0, 0, 0, FALSE} 1809 }, /* BR_RANGE_S256 */ 1810 { 1811 {0, 0, 0xFFFFF, FALSE}, 1812 {4, 20, 0x1F, FALSE}, 1813 {0, 0, 0, FALSE} 1814 }, /* BR_RANGE_S16K */ 1815 { 1816 {0, 8, 0x7FF, FALSE}, 1817 {0, 20, 0x1F, FALSE}, 1818 {0, 0, 0, FALSE} 1819 }, /* BR_RANGE_S64K */ 1820 { 1821 {0, 8, 0x7FF, FALSE}, 1822 {0, 20, 0x1F, FALSE}, 1823 {0, 0, 0, FALSE} 1824 }, /* BR_RANGE_S16M */ 1825 { 1826 {0, 8, 0x7FF, FALSE}, 1827 {0, 20, 0x1F, FALSE}, 1828 {0, 0, 0, FALSE} 1829 } /* BR_RANGE_U4G */ 1830 }, /* relax_code_condition */ 1831 {4, 8, 8, 8, 16}, /* relax_code_size */ 1832 {4, 4, 4, 4, 4}, /* relax_branch_isize */ 1833 { 1834 { 1835 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, 1836 {0, 0, 0, 0} 1837 }, /* BR_RANGE_S256 */ 1838 { 1839 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16}, 1840 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7}, 1841 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL}, 1842 {0, 0, 0, 0} 1843 }, /* BR_RANGE_S16K */ 1844 { 1845 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, 1846 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 1847 {0, 0, 0, 0} 1848 }, /* BR_RANGE_S64K */ 1849 { 1850 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, 1851 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL}, 1852 {0, 0, 0, 0} 1853 }, /* BR_RANGE_S16M */ 1854 { 1855 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL}, 1856 {4, 4, 0, BFD_RELOC_NDS32_HI20}, 1857 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI}, 1858 {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16}, 1859 {0, 0, 0, 0} 1860 } /* BR_RANGE_U4G */ 1861 } /* relax_fixup */ 1862 }, 1863 { 1864 NULL, /* opcode */ 1865 0, /* br_range */ 1866 {{0, 0, 0, FALSE}}, /* cond_field */ 1867 {{0}}, /* relax_code_seq */ 1868 {{{0, 0, 0, FALSE}}}, /* relax_code_condition */ 1869 {0}, /* relax_code_size */ 1870 {0}, /* relax_branch_isize */ 1871 {{{0, 0, 0, 0}}}, /* relax_fixup */ 1872 }, 1873 }; 1874 1875 /* GAS definitions for command-line options. */ 1876 enum options 1877 { 1878 OPTION_BIG = OPTION_MD_BASE, 1879 OPTION_LITTLE, 1880 OPTION_TURBO, 1881 OPTION_PIC, 1882 OPTION_RELAX_FP_AS_GP_OFF, 1883 OPTION_RELAX_B2BB_ON, 1884 OPTION_RELAX_ALL_OFF, 1885 OPTION_OPTIMIZE, 1886 OPTION_OPTIMIZE_SPACE 1887 }; 1888 1889 const char *md_shortopts = "m:O:"; 1890 struct option md_longopts[] = 1891 { 1892 {"O1", no_argument, NULL, OPTION_OPTIMIZE}, 1893 {"Os", no_argument, NULL, OPTION_OPTIMIZE_SPACE}, 1894 {"big", no_argument, NULL, OPTION_BIG}, 1895 {"little", no_argument, NULL, OPTION_LITTLE}, 1896 {"EB", no_argument, NULL, OPTION_BIG}, 1897 {"EL", no_argument, NULL, OPTION_LITTLE}, 1898 {"meb", no_argument, NULL, OPTION_BIG}, 1899 {"mel", no_argument, NULL, OPTION_LITTLE}, 1900 {"mall-ext", no_argument, NULL, OPTION_TURBO}, 1901 {"mext-all", no_argument, NULL, OPTION_TURBO}, 1902 {"mpic", no_argument, NULL, OPTION_PIC}, 1903 /* Relaxation related options. */ 1904 {"mno-fp-as-gp-relax", no_argument, NULL, OPTION_RELAX_FP_AS_GP_OFF}, 1905 {"mb2bb", no_argument, NULL, OPTION_RELAX_B2BB_ON}, 1906 {"mno-all-relax", no_argument, NULL, OPTION_RELAX_ALL_OFF}, 1907 {NULL, no_argument, NULL, 0} 1908 }; 1909 1910 size_t md_longopts_size = sizeof (md_longopts); 1911 1912 struct nds32_parse_option_table 1913 { 1914 const char *name; /* Option string. */ 1915 char *help; /* Help description. */ 1916 int (*func) (char *arg); /* How to parse it. */ 1917 }; 1918 1919 1920 /* The value `-1' represents this option has *NOT* been set. */ 1921 #ifdef NDS32_DEFAULT_ARCH_NAME 1922 static char* nds32_arch_name = NDS32_DEFAULT_ARCH_NAME; 1923 #else 1924 static char* nds32_arch_name = "v3"; 1925 #endif 1926 static int nds32_baseline = -1; 1927 static int nds32_gpr16 = -1; 1928 static int nds32_fpu_sp_ext = -1; 1929 static int nds32_fpu_dp_ext = -1; 1930 static int nds32_freg = -1; 1931 static int nds32_abi = -1; 1932 1933 /* Record ELF flags */ 1934 static int nds32_elf_flags = 0; 1935 static int nds32_fpu_com = 0; 1936 1937 static int nds32_parse_arch (char *str); 1938 static int nds32_parse_baseline (char *str); 1939 static int nds32_parse_freg (char *str); 1940 static int nds32_parse_abi (char *str); 1941 1942 static struct nds32_parse_option_table parse_opts [] = 1943 { 1944 {"arch=", N_("<arch name>\t Assemble for architecture <arch name>\n\ 1945 <arch name> could be\n\ 1946 v3, v3j, v3m, v3f, v3s, "\ 1947 "v2, v2j, v2f, v2s"), nds32_parse_arch}, 1948 {"baseline=", N_("<baseline>\t Assemble for baseline <baseline>\n\ 1949 <baseline> could be v2, v3, v3m"), 1950 nds32_parse_baseline}, 1951 {"fpu-freg=", N_("<freg>\t Specify a FPU configuration\n\ 1952 <freg>\n\ 1953 0: 8 SP / 4 DP registers\n\ 1954 1: 16 SP / 8 DP registers\n\ 1955 2: 32 SP / 16 DP registers\n\ 1956 3: 32 SP / 32 DP registers"), nds32_parse_freg}, 1957 {"abi=", N_("<abi>\t Specify a abi version\n\ 1958 <abi> could be v1, v2, v2fp, v2fpp"), nds32_parse_abi}, 1959 {NULL, NULL, NULL} 1960 }; 1961 1962 static int nds32_mac = 1; 1963 static int nds32_div = 1; 1964 static int nds32_16bit_ext = 1; 1965 static int nds32_dx_regs = 1; 1966 static int nds32_perf_ext = 1; 1967 static int nds32_perf_ext2 = 1; 1968 static int nds32_string_ext = 1; 1969 static int nds32_audio_ext = 1; 1970 static int nds32_fpu_fma = 0; 1971 static int nds32_pic = 0; 1972 static int nds32_relax_fp_as_gp = 1; 1973 static int nds32_relax_b2bb = 0; 1974 static int nds32_relax_all = 1; 1975 struct nds32_set_option_table 1976 { 1977 const char *name; /* Option string. */ 1978 char *help; /* Help description. */ 1979 int *var; /* Variable to be set. */ 1980 int value; /* Value to set. */ 1981 }; 1982 1983 /* The option in this group has both Enable/Disable settings. 1984 Just list on here. */ 1985 1986 static struct nds32_set_option_table toggle_opts [] = 1987 { 1988 {"mac", N_("Multiply instructions support"), &nds32_mac, 1}, 1989 {"div", N_("Divide instructions support"), &nds32_div, 1}, 1990 {"16bit-ext", N_("16-bit extension"), &nds32_16bit_ext, 1}, 1991 {"dx-regs", N_("d0/d1 registers"), &nds32_dx_regs, 1}, 1992 {"perf-ext", N_("Performance extension"), &nds32_perf_ext, 1}, 1993 {"perf2-ext", N_("Performance extension 2"), &nds32_perf_ext2, 1}, 1994 {"string-ext", N_("String extension"), &nds32_string_ext, 1}, 1995 {"reduced-regs", N_("Reduced Register configuration (GPR16) option"), &nds32_gpr16, 1}, 1996 {"audio-isa-ext", N_("AUDIO ISA extension"), &nds32_audio_ext, 1}, 1997 {"fpu-sp-ext", N_("FPU SP extension"), &nds32_fpu_sp_ext, 1}, 1998 {"fpu-dp-ext", N_("FPU DP extension"), &nds32_fpu_dp_ext, 1}, 1999 {"fpu-fma", N_("FPU fused-multiply-add instructions"), &nds32_fpu_fma, 1}, 2000 {NULL, NULL, NULL, 0} 2001 }; 2002 2003 2004 /* GAS declarations. */ 2005 2006 /* This is the callback for nds32-asm.c to parse operands. */ 2007 int 2008 nds32_asm_parse_operand (struct nds32_asm_desc *pdesc, 2009 struct nds32_asm_insn *pinsn, 2010 char **pstr, int64_t *value); 2011 2012 2013 struct nds32_asm_desc asm_desc; 2014 2015 /* md_after_parse_args () 2016 2017 GAS will call md_after_parse_args whenever it is defined. 2018 This function checks any conflicting options specified. */ 2019 2020 void 2021 nds32_after_parse_args (void) 2022 { 2023 /* If -march option is not used in command-line, set the value of option 2024 variable according to NDS32_DEFAULT_ARCH_NAME. */ 2025 nds32_parse_arch (nds32_arch_name); 2026 } 2027 2028 /* This function is called when printing usage message (--help). */ 2029 2030 void 2031 md_show_usage (FILE *stream) 2032 { 2033 struct nds32_parse_option_table *coarse_tune; 2034 struct nds32_set_option_table *fine_tune; 2035 2036 fprintf (stream, _("\n NDS32-specific assembler options:\n")); 2037 fprintf (stream, _("\ 2038 -O1, Optimize for performance\n\ 2039 -Os Optimize for space\n")); 2040 fprintf (stream, _("\ 2041 -EL, -mel or -little Produce little endian output\n\ 2042 -EB, -meb or -big Produce big endian output\n\ 2043 -mpic Generate PIC\n\ 2044 -mno-fp-as-gp-relax Suppress fp-as-gp relaxation for this file\n\ 2045 -mb2bb-relax Back-to-back branch optimization\n\ 2046 -mno-all-relax Suppress all relaxation for this file\n")); 2047 2048 for (coarse_tune = parse_opts; coarse_tune->name != NULL; coarse_tune++) 2049 { 2050 if (coarse_tune->help != NULL) 2051 fprintf (stream, _(" -m%s%s\n"), 2052 coarse_tune->name, _(coarse_tune->help)); 2053 } 2054 2055 for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++) 2056 { 2057 if (fine_tune->help != NULL) 2058 fprintf (stream, _(" -m[no-]%-17sEnable/Disable %s\n"), 2059 fine_tune->name, _(fine_tune->help)); 2060 } 2061 2062 fprintf (stream, _("\ 2063 -mall-ext Turn on all extensions and instructions support\n")); 2064 } 2065 2066 void 2067 nds32_frag_init (fragS *fragp) 2068 { 2069 fragp->tc_frag_data.flag = 0; 2070 fragp->tc_frag_data.opcode = NULL; 2071 fragp->tc_frag_data.fixup = NULL; 2072 } 2073 2074 2075 2076 /* This function reads an expression from a C string and returns a pointer past 2077 the end of the expression. */ 2078 2079 static char * 2080 parse_expression (char *str, expressionS *exp) 2081 { 2082 char *s; 2083 char *tmp; 2084 2085 tmp = input_line_pointer; /* Save line pointer. */ 2086 input_line_pointer = str; 2087 expression (exp); 2088 s = input_line_pointer; 2089 input_line_pointer = tmp; /* Restore line pointer. */ 2090 2091 return s; /* Return pointer to where parsing stopped. */ 2092 } 2093 2094 void 2095 nds32_start_line_hook (void) 2096 { 2097 } 2098 2099 /* 2100 * Pseudo opcodes 2101 */ 2102 2103 typedef void (*nds32_pseudo_opcode_func) (int argc, char *argv[], int pv); 2104 struct nds32_pseudo_opcode 2105 { 2106 const char *opcode; 2107 int argc; 2108 nds32_pseudo_opcode_func proc; 2109 int pseudo_val; 2110 2111 /* Some instructions are not pseudo opcode, but they might still be 2112 expanded or changed with other instruction combination for some 2113 conditions. We also apply this structure to assist such work. 2114 2115 For example, if the distance of branch target '.L0' is larger than 2116 imm8s<<1 range, 2117 2118 the instruction: 2119 2120 beqzs8 .L0 2121 2122 will be transformed into: 2123 2124 bnezs8 .LCB0 2125 j .L0 2126 .LCB0: 2127 2128 However, sometimes we do not want assembler to do such changes 2129 because compiler knows how to generate corresponding instruction sequence. 2130 Use this field to indicate that this opcode is also a physical instruction. 2131 If the flag 'verbatim' is nozero and this opcode 2132 is a physical instruction, we should not expand it. */ 2133 int physical_op; 2134 }; 2135 #define PV_DONT_CARE 0 2136 2137 static struct hash_control *nds32_pseudo_opcode_hash = NULL; 2138 2139 static int 2140 builtin_isreg (const char *s, const char *x ATTRIBUTE_UNUSED) 2141 { 2142 if (s [0] == '$' && hash_find (nds32_gprs_hash, (s + 1))) 2143 return 1; 2144 return 0; 2145 } 2146 2147 static int 2148 builtin_regnum (const char *s, const char *x ATTRIBUTE_UNUSED) 2149 { 2150 struct nds32_keyword *k; 2151 if (*s != '$') 2152 return -1; 2153 s++; 2154 k = hash_find (nds32_gprs_hash, s); 2155 2156 if (k == NULL) 2157 return -1; 2158 2159 return k->value; 2160 } 2161 2162 static int 2163 builtin_addend (const char *s, char *x ATTRIBUTE_UNUSED) 2164 { 2165 const char *ptr = s; 2166 2167 while (*ptr != '+' && *ptr != '-' && *ptr) 2168 ++ptr; 2169 2170 if (*ptr == 0) 2171 return 0; 2172 else 2173 return strtol (ptr, NULL, 0); 2174 } 2175 2176 static void 2177 md_assemblef (char *format, ...) 2178 { 2179 /* FIXME: hope this is long enough. */ 2180 char line[1024]; 2181 va_list ap; 2182 unsigned int r; 2183 2184 va_start (ap, format); 2185 r = vsnprintf (line, sizeof (line), format, ap); 2186 md_assemble (line); 2187 2188 gas_assert (r < sizeof (line)); 2189 } 2190 2191 /* Some prototypes here, since some op may use another op. */ 2192 static void do_pseudo_li_internal (char *rt, int imm32s); 2193 static void do_pseudo_move_reg_internal (char *dst, char *src); 2194 2195 static void 2196 do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2197 { 2198 char *arg_label = argv[0]; 2199 relaxing = TRUE; 2200 /* b label */ 2201 if (nds32_pic && strstr (arg_label, "@PLT")) 2202 { 2203 md_assemblef ("sethi $ta,hi20(%s)", arg_label); 2204 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label); 2205 md_assemble ("add $ta,$ta,$gp"); 2206 md_assemble ("jr $ta"); 2207 } 2208 else 2209 { 2210 md_assemblef ("j %s", arg_label); 2211 } 2212 relaxing = FALSE; 2213 } 2214 2215 static void 2216 do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2217 { 2218 char *arg_label = argv[0]; 2219 relaxing = TRUE; 2220 /* bal|call label */ 2221 if (nds32_pic 2222 && (strstr (arg_label, "@GOT") || strstr (arg_label, "@PLT"))) 2223 { 2224 md_assemblef ("sethi $ta,hi20(%s)", arg_label); 2225 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label); 2226 md_assemble ("add $ta,$ta,$gp"); 2227 md_assemble ("jral $ta"); 2228 } 2229 else 2230 { 2231 md_assemblef ("jal %s", arg_label); 2232 } 2233 relaxing = FALSE; 2234 } 2235 2236 static void 2237 do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2238 { 2239 /* rt5, ra5, label */ 2240 md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]); 2241 md_assemblef ("beqz $ta,%s", argv[2]); 2242 } 2243 2244 static void 2245 do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2246 { 2247 /* rt5, ra5, label */ 2248 md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]); 2249 md_assemblef ("beqz $ta,%s", argv[2]); 2250 } 2251 2252 static void 2253 do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2254 { 2255 /* bgt rt5, ra5, label */ 2256 md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]); 2257 md_assemblef ("bnez $ta,%s", argv[2]); 2258 } 2259 2260 static void 2261 do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2262 { 2263 /* bgt rt5, ra5, label */ 2264 md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]); 2265 md_assemblef ("bnez $ta,%s", argv[2]); 2266 } 2267 2268 static void 2269 do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2270 { 2271 /* bgt rt5, ra5, label */ 2272 md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]); 2273 md_assemblef ("beqz $ta,%s", argv[2]); 2274 } 2275 2276 static void 2277 do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2278 { 2279 /* bgt rt5, ra5, label */ 2280 md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]); 2281 md_assemblef ("beqz $ta,%s", argv[2]); 2282 } 2283 2284 static void 2285 do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2286 { 2287 /* rt5, ra5, label */ 2288 md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]); 2289 md_assemblef ("bnez $ta,%s", argv[2]); 2290 } 2291 2292 static void 2293 do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2294 { 2295 /* rt5, ra5, label */ 2296 md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]); 2297 md_assemblef ("bnez $ta,%s", argv[2]); 2298 } 2299 2300 static void 2301 do_pseudo_br (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2302 { 2303 md_assemblef ("jr %s", argv[0]); 2304 } 2305 2306 static void 2307 do_pseudo_bral (int argc, char *argv[], int pv ATTRIBUTE_UNUSED) 2308 { 2309 if (argc == 1) 2310 md_assemblef ("jral $lp,%s", argv[0]); 2311 else 2312 md_assemblef ("jral %s,%s", argv[0], argv[1]); 2313 } 2314 2315 static void 2316 do_pseudo_la_internal (const char *arg_reg, char *arg_label, 2317 const char *line) 2318 { 2319 expressionS exp; 2320 2321 parse_expression (arg_label, &exp); 2322 if (exp.X_op != O_symbol) 2323 { 2324 as_bad (_("la must use with symbol. '%s'"), line); 2325 return; 2326 } 2327 2328 relaxing = TRUE; 2329 /* rt, label */ 2330 if (!nds32_pic && !strstr(arg_label, "@")) 2331 { 2332 md_assemblef ("sethi %s,hi20(%s)", arg_reg, arg_label); 2333 md_assemblef ("ori %s,%s,lo12(%s)", arg_reg, arg_reg, arg_label); 2334 } 2335 else if (strstr (arg_label, "@TPOFF")) 2336 { 2337 /* la $rt, sym@TPOFF */ 2338 md_assemblef ("sethi $ta,hi20(%s)", arg_label); 2339 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label); 2340 md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG); 2341 } 2342 else if (strstr(arg_label, "@GOTTPOFF")) 2343 { 2344 /* la $rt, sym@GOTTPOFF*/ 2345 md_assemblef ("sethi $ta,hi20(%s)", arg_label); 2346 md_assemblef ("lwi $ta,[$ta+lo12(%s)]", arg_label); 2347 md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG); 2348 } 2349 else if (nds32_pic && ((strstr (arg_label, "@PLT") 2350 || strstr (arg_label, "@GOTOFF")))) 2351 { 2352 md_assemblef ("sethi $ta,hi20(%s)", arg_label); 2353 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label); 2354 md_assemblef ("add %s,$ta,$gp", arg_reg); 2355 } 2356 else if (nds32_pic && strstr (arg_label, "@GOT")) 2357 { 2358 long addend = builtin_addend (arg_label, NULL); 2359 2360 md_assemblef ("sethi $ta,hi20(%s)", arg_label); 2361 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label); 2362 md_assemblef ("lw %s,[$gp+$ta]", arg_reg); 2363 if (addend != 0) 2364 { 2365 if (addend < 0x4000 && addend >= -0x4000) 2366 { 2367 md_assemblef ("addi %s,%s,%d", arg_reg, arg_reg, addend); 2368 } 2369 else 2370 { 2371 do_pseudo_li_internal ("$ta", addend); 2372 md_assemblef ("add %s,$ta,%s", arg_reg, arg_reg); 2373 } 2374 } 2375 } 2376 else 2377 as_bad (_("need PIC qualifier with symbol. '%s'"), line); 2378 relaxing = FALSE; 2379 } 2380 2381 static void 2382 do_pseudo_la (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2383 { 2384 do_pseudo_la_internal (argv[0], argv[1], argv[argc]); 2385 } 2386 2387 static void 2388 do_pseudo_li_internal (char *rt, int imm32s) 2389 { 2390 if (enable_16bit && imm32s <= 0xf && imm32s >= -0x10) 2391 md_assemblef ("movi55 %s,%d", rt, imm32s); 2392 else if (imm32s <= 0x7ffff && imm32s >= -0x80000) 2393 md_assemblef ("movi %s,%d", rt, imm32s); 2394 else if ((imm32s & 0xfff) == 0) 2395 md_assemblef ("sethi %s,hi20(%d)", rt, imm32s); 2396 else 2397 { 2398 md_assemblef ("sethi %s,hi20(%d)", rt, imm32s); 2399 md_assemblef ("ori %s,%s,lo12(%d)", rt, rt, imm32s); 2400 } 2401 } 2402 2403 static void 2404 do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2405 { 2406 /* Validate argv[1] for constant expression. */ 2407 expressionS exp; 2408 2409 parse_expression (argv[1], &exp); 2410 if (exp.X_op != O_constant) 2411 { 2412 as_bad (_("Operand is not a constant. `%s'"), argv[argc]); 2413 return; 2414 } 2415 2416 do_pseudo_li_internal (argv[0], exp.X_add_number); 2417 } 2418 2419 static void 2420 do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[], int pv) 2421 { 2422 char ls = 'r'; 2423 char size = 'x'; 2424 const char *sign = ""; 2425 2426 /* Prepare arguments for various load/store. */ 2427 sign = (pv & 0x10) ? "s" : ""; 2428 ls = (pv & 0x80000000) ? 's' : 'l'; 2429 switch (pv & 0x3) 2430 { 2431 case 0: size = 'b'; break; 2432 case 1: size = 'h'; break; 2433 case 2: size = 'w'; break; 2434 } 2435 2436 if (ls == 's' || size == 'w') 2437 sign = ""; 2438 2439 if (builtin_isreg (argv[1], NULL)) 2440 { 2441 /* lwi */ 2442 md_assemblef ("%c%ci %s,[%s]", ls, size, argv[0], argv[1]); 2443 } 2444 else if (!nds32_pic) 2445 { 2446 relaxing = TRUE; 2447 if (strstr (argv[1], "@TPOFF")) 2448 { 2449 /* ls.w $rt, sym@TPOFF */ 2450 md_assemblef ("sethi $ta,hi20(%s)", argv[1]); 2451 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]); 2452 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG); 2453 } 2454 else if (strstr (argv[1], "@GOTTPOFF")) 2455 { 2456 /* ls.w $rt, sym@GOTTPOFF */ 2457 md_assemblef ("sethi $ta,hi20(%s)", argv[1]); 2458 md_assemblef ("lwi $ta,[$ta+lo12(%s)]", argv[1]); 2459 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG); 2460 } 2461 else 2462 { 2463 /* lwi */ 2464 md_assemblef ("sethi $ta,hi20(%s)", argv[1]); 2465 md_assemblef ("%c%c%si %s,[$ta+lo12(%s)]", ls, size, sign, argv[0], argv[1]); 2466 } 2467 relaxing = FALSE; 2468 } 2469 else 2470 { 2471 relaxing = TRUE; 2472 /* PIC code. */ 2473 if (strstr (argv[1], "@GOTOFF")) 2474 { 2475 /* lw */ 2476 md_assemblef ("sethi $ta,hi20(%s)", argv[1]); 2477 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]); 2478 md_assemblef ("%c%c%s %s,[$ta+$gp]", ls, size, sign, argv[0]); 2479 } 2480 else if (strstr (argv[1], "@GOT")) 2481 { 2482 long addend = builtin_addend (argv[1], NULL); 2483 /* lw */ 2484 md_assemblef ("sethi $ta,hi20(%s)", argv[1]); 2485 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]); 2486 md_assemble ("lw $ta,[$gp+$ta]"); /* Load address word. */ 2487 if (addend < 0x10000 && addend >= -0x10000) 2488 { 2489 md_assemblef ("%c%c%si %s,[$ta+(%d)]", ls, size, sign, argv[0], addend); 2490 } 2491 else 2492 { 2493 /* lw */ 2494 do_pseudo_li_internal (argv[0], addend); 2495 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], argv[0]); 2496 } 2497 } 2498 else 2499 { 2500 as_bad (_("needs @GOT or @GOTOFF. %s"), argv[argc]); 2501 } 2502 relaxing = FALSE; 2503 } 2504 } 2505 2506 static void 2507 do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[], int pv) 2508 { 2509 char *arg_rt = argv[0]; 2510 char *arg_label = argv[1]; 2511 char *arg_inc = argv[2]; 2512 char ls = 'r'; 2513 char size = 'x'; 2514 const char *sign = ""; 2515 2516 /* Prepare arguments for various load/store. */ 2517 sign = (pv & 0x10) ? "s" : ""; 2518 ls = (pv & 0x80000000) ? 's' : 'l'; 2519 switch (pv & 0x3) 2520 { 2521 case 0: size = 'b'; break; 2522 case 1: size = 'h'; break; 2523 case 2: size = 'w'; break; 2524 } 2525 2526 if (ls == 's' || size == 'w') 2527 sign = ""; 2528 2529 do_pseudo_la_internal ("$ta", arg_label, argv[argc]); 2530 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc); 2531 } 2532 2533 static void 2534 do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[], int pv) 2535 { 2536 char *arg_rt = argv[0]; 2537 char *arg_inc = argv[1]; 2538 char ls = 'r'; 2539 char size = 'x'; 2540 const char *sign = ""; 2541 2542 /* Prepare arguments for various load/store. */ 2543 sign = (pv & 0x10) ? "s" : ""; 2544 ls = (pv & 0x80000000) ? 's' : 'l'; 2545 switch (pv & 0x3) 2546 { 2547 case 0: size = 'b'; break; 2548 case 1: size = 'h'; break; 2549 case 2: size = 'w'; break; 2550 } 2551 2552 if (ls == 's' || size == 'w') 2553 sign = ""; 2554 2555 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc); 2556 } 2557 2558 static void 2559 do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED, char *argv[], int pv) 2560 { 2561 char ls = 'r'; 2562 char size = 'x'; 2563 const char *sign = ""; 2564 2565 /* Prepare arguments for various load/store. */ 2566 sign = (pv & 0x10) ? "s" : ""; 2567 ls = (pv & 0x80000000) ? 's' : 'l'; 2568 switch (pv & 0x3) 2569 { 2570 case 0: size = 'b'; break; 2571 case 1: size = 'h'; break; 2572 case 2: size = 'w'; break; 2573 } 2574 2575 if (ls == 's' || size == 'w') 2576 sign = ""; 2577 2578 md_assemblef ("%c%c%si.bi %s,%s,%s", 2579 ls, size, sign, argv[0], argv[1], argv[2]); 2580 } 2581 2582 static void 2583 do_pseudo_move_reg_internal (char *dst, char *src) 2584 { 2585 if (enable_16bit) 2586 md_assemblef ("mov55 %s,%s", dst, src); 2587 else 2588 md_assemblef ("ori %s,%s,0", dst, src); 2589 } 2590 2591 static void 2592 do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2593 { 2594 expressionS exp; 2595 2596 if (builtin_isreg (argv[1], NULL)) 2597 do_pseudo_move_reg_internal (argv[0], argv[1]); 2598 else 2599 { 2600 parse_expression (argv[1], &exp); 2601 if (exp.X_op == O_constant) 2602 /* move $rt, imm -> li $rt, imm */ 2603 do_pseudo_li_internal (argv[0], exp.X_add_number); 2604 else 2605 /* l.w $rt, var -> l.w $rt, var */ 2606 do_pseudo_ls_bhw (argc, argv, 2); 2607 } 2608 } 2609 2610 static void 2611 do_pseudo_neg (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2612 { 2613 /* Instead of "subri". */ 2614 md_assemblef ("subri %s,%s,0", argv[0], argv[1]); 2615 } 2616 2617 static void 2618 do_pseudo_not (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2619 { 2620 md_assemblef ("nor %s,%s,%s", argv[0], argv[1], argv[1]); 2621 } 2622 2623 static void 2624 do_pseudo_pushpopm (int argc, char *argv[], int pv ATTRIBUTE_UNUSED) 2625 { 2626 /* posh/pop $ra, $rb */ 2627 /* SMW.{b | a}{i | d}{m?} Rb, [Ra], Re, Enable4 */ 2628 int rb, re, ra, en4; 2629 int i; 2630 char *opc = "pushpopm"; 2631 2632 if (argc == 3) 2633 as_bad ("'pushm/popm $ra5, $rb5, $label' is deprecated. " 2634 "Only 'pushm/popm $ra5' is supported now. %s", argv[argc]); 2635 else if (argc == 1) 2636 as_bad ("'pushm/popm $ra5, $rb5'. %s\n", argv[argc]); 2637 2638 if (strstr (argv[argc], "pop") == argv[argc]) 2639 opc = "lmw.bim"; 2640 else if (strstr (argv[argc], "push") == argv[argc]) 2641 opc = "smw.adm"; 2642 else 2643 as_fatal ("nds32-as internal error. %s", argv[argc]); 2644 2645 rb = builtin_regnum (argv[0], NULL); 2646 re = builtin_regnum (argv[1], NULL); 2647 2648 if (re < rb) 2649 { 2650 as_warn ("$rb should not be smaller than $ra. %s", argv[argc]); 2651 /* Swap to right order. */ 2652 ra = re; 2653 re = rb; 2654 rb = ra; 2655 } 2656 2657 /* Build enable4 mask. */ 2658 en4 = 0; 2659 if (re >= 28 || rb >= 28) 2660 { 2661 for (i = (rb >= 28? rb: 28); i <= re; i++) 2662 en4 |= 1 << (3 - (i - 28)); 2663 } 2664 2665 /* Adjust $re, $rb. */ 2666 if (rb >= 28) 2667 rb = re = 31; 2668 else if (nds32_gpr16 != 1 && re >= 28) 2669 re = 27; 2670 2671 /* Reduce register. */ 2672 if (nds32_gpr16 && re > 10 && !(rb == 31 && re == 31)) 2673 { 2674 if (re >= 15 && strstr(opc, "smw") != NULL) 2675 md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4); 2676 if (rb <= 10) 2677 md_assemblef ("%s $r%d,[$sp],$r10, 0x0", opc, rb); 2678 if (re >= 15 && strstr(opc, "lmw") != NULL) 2679 md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4); 2680 } 2681 else 2682 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4); 2683 } 2684 2685 static void 2686 do_pseudo_pushpop (int argc, char *argv[], int pv ATTRIBUTE_UNUSED) 2687 { 2688 /* push/pop $ra5, $label=$sp */ 2689 char *argvm[3]; 2690 2691 if (argc == 2) 2692 as_bad ("'push/pop $ra5, rb5' is deprecated. " 2693 "Only 'push/pop $ra5' is supported now. %s", argv[argc]); 2694 2695 argvm[0] = argv[0]; 2696 argvm[1] = argv[0]; 2697 argvm[2] = argv[argc]; 2698 do_pseudo_pushpopm (2, argvm, PV_DONT_CARE); 2699 } 2700 2701 static void 2702 do_pseudo_v3push (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2703 { 2704 md_assemblef ("push25 %s,%s", argv[0], argv[1]); 2705 } 2706 2707 static void 2708 do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2709 { 2710 md_assemblef ("pop25 %s,%s", argv[0], argv[1]); 2711 } 2712 2713 /* pv == 0, parsing "push.s" pseudo instruction operands. 2714 pv != 0, parsing "pop.s" pseudo instruction operands. */ 2715 2716 static void 2717 do_pseudo_pushpop_stack (int argc, char *argv[], int pv) 2718 { 2719 /* push.s Rb,Re,{$fp $gp $lp $sp} ==> smw.adm Rb,[$sp],Re,Eable4 */ 2720 /* pop.s Rb,Re,{$fp $gp $lp $sp} ==> lmw.bim Rb,[$sp],Re,Eable4 */ 2721 2722 int rb, re; 2723 int en4; 2724 int last_arg_index; 2725 char *opc = (pv == 0) ? "smw.adm" : "lmw.bim"; 2726 2727 rb = re = 0; 2728 2729 if (argc == 1) 2730 { 2731 /* argc=1, operands pattern: { $fp $gp $lp $sp } */ 2732 2733 /* Set register number Rb = Re = $sp = $r31. */ 2734 rb = re = 31; 2735 } 2736 else if (argc == 2 || argc == 3) 2737 { 2738 /* argc=2, operands pattern: Rb, Re */ 2739 /* argc=3, operands pattern: Rb, Re, { $fp $gp $lp $sp } */ 2740 2741 /* Get register number in integer. */ 2742 rb = builtin_regnum (argv[0], NULL); 2743 re = builtin_regnum (argv[1], NULL); 2744 2745 /* Rb should be equal/less than Re. */ 2746 if (rb > re) 2747 as_bad ("The first operand (%s) should be equal to or smaller than " 2748 "second operand (%s).", argv[0], argv[1]); 2749 2750 /* forbid using $fp|$gp|$lp|$sp in Rb or Re 2751 r28 r29 r30 r31 */ 2752 if (rb >= 28) 2753 as_bad ("Cannot use $fp, $gp, $lp, or $sp at first operand !!"); 2754 if (re >= 28) 2755 as_bad ("Cannot use $fp, $gp, $lp, or $sp at second operand !!"); 2756 } 2757 else 2758 { 2759 as_bad ("Invalid operands pattern !!"); 2760 } 2761 2762 /* Build Enable4 mask. */ 2763 /* Using last_arg_index for argc=1|2|3 is safe, because $fp, $gp, $lp, 2764 and $sp only appear in argc=1 or argc=3 if argc=2, en4 remains 0, 2765 which is also valid for code generation. */ 2766 en4 = 0; 2767 last_arg_index = argc - 1; 2768 if (strstr (argv[last_arg_index], "$fp")) 2769 en4 |= 8; 2770 if (strstr (argv[last_arg_index], "$gp")) 2771 en4 |= 4; 2772 if (strstr (argv[last_arg_index], "$lp")) 2773 en4 |= 2; 2774 if (strstr (argv[last_arg_index], "$sp")) 2775 en4 |= 1; 2776 2777 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4); 2778 } 2779 2780 static void 2781 do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2782 { 2783 char size = 'x'; 2784 /* If users omit push location, use $sp as default value. */ 2785 char location[8] = "$sp"; /* 8 is enough for register name. */ 2786 2787 switch (pv & 0x3) 2788 { 2789 case 0: size = 'b'; break; 2790 case 1: size = 'h'; break; 2791 case 2: size = 'w'; break; 2792 case 3: size = 'w'; break; 2793 } 2794 2795 if (argc == 2) 2796 { 2797 strncpy (location, argv[1], 8); 2798 location[7] = '\0'; 2799 } 2800 2801 md_assemblef ("l.%c $ta,%s", size, argv[0]); 2802 md_assemblef ("smw.adm $ta,[%s],$ta", location); 2803 2804 if ((pv & 0x3) == 0x3) /* double-word */ 2805 { 2806 md_assemblef ("l.w $ta,%s+4", argv[0]); 2807 md_assemblef ("smw.adm $ta,[%s],$ta", location); 2808 } 2809 } 2810 2811 static void 2812 do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2813 { 2814 char size = 'x'; 2815 /* If users omit pop location, use $sp as default value. */ 2816 char location[8] = "$sp"; /* 8 is enough for register name. */ 2817 2818 switch (pv & 0x3) 2819 { 2820 case 0: size = 'b'; break; 2821 case 1: size = 'h'; break; 2822 case 2: size = 'w'; break; 2823 case 3: size = 'w'; break; 2824 } 2825 2826 if (argc == 3) 2827 { 2828 strncpy (location, argv[2], 8); 2829 location[7] = '\0'; 2830 } 2831 2832 if ((pv & 0x3) == 0x3) /* double-word */ 2833 { 2834 md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]); 2835 md_assemblef ("s.w %s,%s+4", argv[1], argv[0]); 2836 } 2837 2838 md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]); 2839 md_assemblef ("s.%c %s,%s", size, argv[1], argv[0]); 2840 } 2841 2842 static void 2843 do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2844 { 2845 /* If users omit push location, use $sp as default value. */ 2846 char location[8] = "$sp"; /* 8 is enough for register name. */ 2847 2848 if (argc == 2) 2849 { 2850 strncpy (location, argv[1], 8); 2851 location[7] = '\0'; 2852 } 2853 2854 md_assemblef ("la $ta,%s", argv[0]); 2855 md_assemblef ("smw.adm $ta,[%s],$ta", location); 2856 } 2857 2858 static void 2859 do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED) 2860 { 2861 /* If users omit push location, use $sp as default value. */ 2862 char location[8] = "$sp"; /* 8 is enough for register name. */ 2863 2864 if (argc == 2) 2865 { 2866 strncpy (location, argv[1], 8); 2867 location[7] = '\0'; 2868 } 2869 2870 md_assemblef ("li $ta,%s", argv[0]); 2871 md_assemblef ("smw.adm $ta,[%s],$ta", location); 2872 } 2873 2874 struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] = 2875 { 2876 {"b", 1, do_pseudo_b, 0, 0}, 2877 {"bal", 1, do_pseudo_bal, 0, 0}, 2878 2879 {"bge", 3, do_pseudo_bge, 0, 0}, 2880 {"bges", 3, do_pseudo_bges, 0, 0}, 2881 2882 {"bgt", 3, do_pseudo_bgt, 0, 0}, 2883 {"bgts", 3, do_pseudo_bgts, 0, 0}, 2884 2885 {"ble", 3, do_pseudo_ble, 0, 0}, 2886 {"bles", 3, do_pseudo_bles, 0, 0}, 2887 2888 {"blt", 3, do_pseudo_blt, 0, 0}, 2889 {"blts", 3, do_pseudo_blts, 0, 0}, 2890 2891 {"br", 1, do_pseudo_br, 0, 0}, 2892 {"bral", 1, do_pseudo_bral, 0, 0}, 2893 2894 {"call", 1, do_pseudo_bal, 0, 0}, 2895 2896 {"la", 2, do_pseudo_la, 0, 0}, 2897 {"li", 2, do_pseudo_li, 0, 0}, 2898 2899 {"l.b", 2, do_pseudo_ls_bhw, 0, 0}, 2900 {"l.h", 2, do_pseudo_ls_bhw, 1, 0}, 2901 {"l.w", 2, do_pseudo_ls_bhw, 2, 0}, 2902 {"l.bs", 2, do_pseudo_ls_bhw, 0 | 0x10, 0}, 2903 {"l.hs", 2, do_pseudo_ls_bhw, 1 | 0x10, 0}, 2904 {"s.b", 2, do_pseudo_ls_bhw, 0 | 0x80000000, 0}, 2905 {"s.h", 2, do_pseudo_ls_bhw, 1 | 0x80000000, 0}, 2906 {"s.w", 2, do_pseudo_ls_bhw, 2 | 0x80000000, 0}, 2907 2908 {"l.bp", 3, do_pseudo_ls_bhwp, 0, 0}, 2909 {"l.bpc", 3, do_pseudo_ls_bhwpc, 0, 0}, 2910 {"l.hp", 3, do_pseudo_ls_bhwp, 1, 0}, 2911 {"l.hpc", 3, do_pseudo_ls_bhwpc, 1, 0}, 2912 {"l.wp", 3, do_pseudo_ls_bhwp, 2, 0}, 2913 {"l.wpc", 3, do_pseudo_ls_bhwpc, 2, 0}, 2914 {"l.bsp", 3, do_pseudo_ls_bhwp, 0 | 0x10, 0}, 2915 {"l.bspc", 3, do_pseudo_ls_bhwpc, 0 | 0x10, 0}, 2916 {"l.hsp", 3, do_pseudo_ls_bhwp, 1 | 0x10, 0}, 2917 {"l.hspc", 3, do_pseudo_ls_bhwpc, 1 | 0x10, 0}, 2918 {"s.bp", 3, do_pseudo_ls_bhwp, 0 | 0x80000000, 0}, 2919 {"s.bpc", 3, do_pseudo_ls_bhwpc, 0 | 0x80000000, 0}, 2920 {"s.hp", 3, do_pseudo_ls_bhwp, 1 | 0x80000000, 0}, 2921 {"s.hpc", 3, do_pseudo_ls_bhwpc, 1 | 0x80000000, 0}, 2922 {"s.wp", 3, do_pseudo_ls_bhwp, 2 | 0x80000000, 0}, 2923 {"s.wpc", 3, do_pseudo_ls_bhwpc, 2 | 0x80000000, 0}, 2924 {"s.bsp", 3, do_pseudo_ls_bhwp, 0 | 0x80000000 | 0x10, 0}, 2925 {"s.hsp", 3, do_pseudo_ls_bhwp, 1 | 0x80000000 | 0x10, 0}, 2926 2927 {"lbi.p", 3, do_pseudo_ls_bhwi, 0, 0}, 2928 {"lhi.p", 3, do_pseudo_ls_bhwi, 1, 0}, 2929 {"lwi.p", 3, do_pseudo_ls_bhwi, 2, 0}, 2930 {"sbi.p", 3, do_pseudo_ls_bhwi, 0 | 0x80000000, 0}, 2931 {"shi.p", 3, do_pseudo_ls_bhwi, 1 | 0x80000000, 0}, 2932 {"swi.p", 3, do_pseudo_ls_bhwi, 2 | 0x80000000, 0}, 2933 {"lbsi.p", 3, do_pseudo_ls_bhwi, 0 | 0x10, 0}, 2934 {"lhsi.p", 3, do_pseudo_ls_bhwi, 1 | 0x10, 0}, 2935 {"lwsi.p", 3, do_pseudo_ls_bhwi, 2 | 0x10, 0}, 2936 2937 {"move", 2, do_pseudo_move, 0, 0}, 2938 {"neg", 2, do_pseudo_neg, 0, 0}, 2939 {"not", 2, do_pseudo_not, 0, 0}, 2940 2941 {"pop", 2, do_pseudo_pushpop, 0, 0}, 2942 {"push", 2, do_pseudo_pushpop, 0, 0}, 2943 {"popm", 2, do_pseudo_pushpopm, 0, 0}, 2944 {"pushm", 3, do_pseudo_pushpopm, 0, 0}, 2945 2946 {"v3push", 2, do_pseudo_v3push, 0, 0}, 2947 {"v3pop", 2, do_pseudo_v3pop, 0, 0}, 2948 2949 /* Support pseudo instructions of pushing/poping registers into/from stack 2950 push.s Rb, Re, { $fp $gp $lp $sp } ==> smw.adm Rb,[$sp],Re,Enable4 2951 pop.s Rb, Re, { $fp $gp $lp $sp } ==> lmw.bim Rb,[$sp],Re,Enable4 */ 2952 { "push.s", 3, do_pseudo_pushpop_stack, 0, 0 }, 2953 { "pop.s", 3, do_pseudo_pushpop_stack, 1, 0 }, 2954 { "push.b", 2, do_pseudo_push_bhwd, 0, 0 }, 2955 { "push.h", 2, do_pseudo_push_bhwd, 1, 0 }, 2956 { "push.w", 2, do_pseudo_push_bhwd, 2, 0 }, 2957 { "push.d", 2, do_pseudo_push_bhwd, 3, 0 }, 2958 { "pop.b", 3, do_pseudo_pop_bhwd, 0, 0 }, 2959 { "pop.h", 3, do_pseudo_pop_bhwd, 1, 0 }, 2960 { "pop.w", 3, do_pseudo_pop_bhwd, 2, 0 }, 2961 { "pop.d", 3, do_pseudo_pop_bhwd, 3, 0 }, 2962 { "pusha", 2, do_pseudo_pusha, 0, 0 }, 2963 { "pushi", 2, do_pseudo_pushi, 0, 0 }, 2964 2965 {NULL, 0, NULL, 0, 0} 2966 }; 2967 2968 static void 2969 nds32_init_nds32_pseudo_opcodes (void) 2970 { 2971 struct nds32_pseudo_opcode *opcode = nds32_pseudo_opcode_table; 2972 2973 nds32_pseudo_opcode_hash = hash_new (); 2974 for ( ; opcode->opcode; opcode++) 2975 { 2976 void *op; 2977 2978 op = hash_find (nds32_pseudo_opcode_hash, opcode->opcode); 2979 if (op != NULL) 2980 { 2981 as_warn (_("Duplicated pseudo-opcode %s."), opcode->opcode); 2982 continue; 2983 } 2984 hash_insert (nds32_pseudo_opcode_hash, opcode->opcode, opcode); 2985 } 2986 } 2987 2988 static struct nds32_pseudo_opcode * 2989 nds32_lookup_pseudo_opcode (char *str) 2990 { 2991 int i = 0; 2992 /* Assume pseudo-opcode are less than 16-char in length. */ 2993 char op[16] = {0}; 2994 2995 for (i = 0; i < (int)ARRAY_SIZE (op); i++) 2996 { 2997 if (ISSPACE (op[i] = str[i])) 2998 break; 2999 } 3000 3001 if (i >= (int)ARRAY_SIZE (op)) 3002 return NULL; 3003 3004 op[i] = '\0'; 3005 3006 return hash_find (nds32_pseudo_opcode_hash, op); 3007 } 3008 3009 static void 3010 nds32_pseudo_opcode_wrapper (char *line, struct nds32_pseudo_opcode *opcode) 3011 { 3012 int argc = 0; 3013 char *argv[8] = {NULL}; 3014 char *s; 3015 char *str = xstrdup (line); 3016 3017 /* Parse arguments for opcode. */ 3018 s = str + strlen (opcode->opcode); 3019 3020 if (!s[0]) 3021 goto end; 3022 3023 /* Dummy comma to ease separate arguments as below. */ 3024 s[0] = ','; 3025 do 3026 { 3027 if (s[0] == ',') 3028 { 3029 if (argc >= opcode->argc 3030 || (argc >= (int)ARRAY_SIZE (argv) - 1)) 3031 as_bad (_("Too many argument. `%s'"), line); 3032 3033 argv[argc] = s + 1; 3034 argc ++; 3035 s[0] = '\0'; 3036 } 3037 ++s; 3038 } while (s[0] != '\0'); 3039 end: 3040 /* Put the origin line for debugging. */ 3041 argv[argc] = line; 3042 opcode->proc (argc, argv, opcode->pseudo_val); 3043 free (str); 3044 } 3045 3046 /* This function will be invoked from function `nds32_after_parse_args'. 3047 Thus, if the value of option has been set, keep the value the way it is. */ 3048 3049 static int 3050 nds32_parse_arch (char *str) 3051 { 3052 static const struct nds32_arch 3053 { 3054 const char *name; 3055 int baseline; 3056 int reduced_reg; 3057 int fpu_sp_ext; 3058 int fpu_dp_ext; 3059 int fpu_freg; 3060 int abi; 3061 } archs[] = 3062 { 3063 {"v3m", ISA_V3M, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI}, 3064 {"v3j", ISA_V3, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI}, 3065 {"v3s", ISA_V3, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS}, 3066 {"v3f", ISA_V3, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS}, 3067 {"v3", ISA_V3, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI}, 3068 {"v2j", ISA_V2, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI}, 3069 {"v2s", ISA_V2, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS}, 3070 {"v2f", ISA_V2, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS}, 3071 {"v2", ISA_V2, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI}, 3072 }; 3073 size_t i; 3074 3075 for (i = 0; i < ARRAY_SIZE (archs); i++) 3076 { 3077 if (strcmp (str, archs[i].name) != 0) 3078 continue; 3079 3080 /* The value `-1' represents this option has *NOT* been set. */ 3081 nds32_baseline = (-1 != nds32_baseline) ? nds32_baseline : archs[i].baseline; 3082 nds32_gpr16 = (-1 != nds32_gpr16) ? nds32_gpr16 : archs[i].reduced_reg; 3083 nds32_fpu_sp_ext = (-1 != nds32_fpu_sp_ext) ? nds32_fpu_sp_ext : archs[i].fpu_sp_ext; 3084 nds32_fpu_dp_ext = (-1 != nds32_fpu_dp_ext) ? nds32_fpu_dp_ext : archs[i].fpu_dp_ext; 3085 nds32_freg = (-1 != nds32_freg) ? nds32_freg : archs[i].fpu_freg; 3086 nds32_abi = (-1 != nds32_abi) ? nds32_abi : archs[i].abi; 3087 3088 return 1; 3089 } 3090 3091 /* Logic here rejects the input arch name. */ 3092 as_bad (_("unknown arch name `%s'\n"), str); 3093 3094 return 1; 3095 } 3096 3097 /* This function parses "baseline" specified. */ 3098 3099 static int 3100 nds32_parse_baseline (char *str) 3101 { 3102 if (strcmp (str, "v3") == 0) 3103 nds32_baseline = ISA_V3; 3104 else if (strcmp (str, "v3m") == 0) 3105 nds32_baseline = ISA_V3M; 3106 else if (strcmp (str, "v2") == 0) 3107 nds32_baseline = ISA_V2; 3108 else 3109 { 3110 /* Logic here rejects the input baseline. */ 3111 as_bad (_("unknown baseline `%s'\n"), str); 3112 return 0; 3113 } 3114 3115 return 1; 3116 } 3117 3118 /* This function parses "fpu-freg" specified. */ 3119 3120 static int 3121 nds32_parse_freg (char *str) 3122 { 3123 if (strcmp (str, "2") == 0) 3124 nds32_freg = E_NDS32_FPU_REG_32SP_16DP; 3125 else if (strcmp (str, "3") == 0) 3126 nds32_freg = E_NDS32_FPU_REG_32SP_32DP; 3127 else if (strcmp (str, "1") == 0) 3128 nds32_freg = E_NDS32_FPU_REG_16SP_8DP; 3129 else if (strcmp (str, "0") == 0) 3130 nds32_freg = E_NDS32_FPU_REG_8SP_4DP; 3131 else 3132 { 3133 /* Logic here rejects the input FPU configuration. */ 3134 as_bad (_("unknown FPU configuration `%s'\n"), str); 3135 return 0; 3136 } 3137 3138 return 1; 3139 } 3140 3141 /* This function parse "abi=" specified. */ 3142 3143 static int 3144 nds32_parse_abi (char *str) 3145 { 3146 if (strcmp (str, "v2") == 0) 3147 nds32_abi = E_NDS_ABI_AABI; 3148 /* Obsolete. */ 3149 else if (strcmp (str, "v2fp") == 0) 3150 nds32_abi = E_NDS_ABI_V2FP; 3151 else if (strcmp (str, "v1") == 0) 3152 nds32_abi = E_NDS_ABI_V1; 3153 else if (strcmp (str,"v2fpp") == 0) 3154 nds32_abi = E_NDS_ABI_V2FP_PLUS; 3155 else 3156 { 3157 /* Logic here rejects the input abi version. */ 3158 as_bad (_("unknown ABI version`%s'\n"), str); 3159 return 0; 3160 } 3161 3162 return 1; 3163 } 3164 3165 /* This function turn on all extensions and instructions support. */ 3166 3167 static int 3168 nds32_all_ext (void) 3169 { 3170 nds32_mac = 1; 3171 nds32_div = 1; 3172 nds32_dx_regs = 1; 3173 nds32_16bit_ext = 1; 3174 nds32_perf_ext = 1; 3175 nds32_perf_ext2 = 1; 3176 nds32_string_ext = 1; 3177 nds32_audio_ext = 1; 3178 nds32_fpu_fma = 1; 3179 nds32_fpu_sp_ext = 1; 3180 nds32_fpu_dp_ext = 1; 3181 3182 return 1; 3183 } 3184 3185 /* GAS will call md_parse_option whenever getopt returns an unrecognized code, 3186 presumably indicating a special code value which appears in md_longopts. 3187 This function should return non-zero if it handled the option and zero 3188 otherwise. There is no need to print a message about an option not being 3189 recognized. This will be handled by the generic code. */ 3190 3191 int 3192 nds32_parse_option (int c, char *arg) 3193 { 3194 struct nds32_parse_option_table *coarse_tune; 3195 struct nds32_set_option_table *fine_tune; 3196 char *ptr_arg = NULL; 3197 3198 switch (c) 3199 { 3200 case OPTION_OPTIMIZE: 3201 optimize = 1; 3202 optimize_for_space = 0; 3203 break; 3204 case OPTION_OPTIMIZE_SPACE: 3205 optimize = 0; 3206 optimize_for_space = 1; 3207 break; 3208 case OPTION_BIG: 3209 target_big_endian = 1; 3210 break; 3211 case OPTION_LITTLE: 3212 target_big_endian = 0; 3213 break; 3214 case OPTION_TURBO: 3215 nds32_all_ext (); 3216 break; 3217 case OPTION_PIC: 3218 nds32_pic = 1; 3219 break; 3220 case OPTION_RELAX_FP_AS_GP_OFF: 3221 nds32_relax_fp_as_gp = 0; 3222 break; 3223 case OPTION_RELAX_B2BB_ON: 3224 nds32_relax_b2bb = 1; 3225 break; 3226 case OPTION_RELAX_ALL_OFF: 3227 nds32_relax_all = 0; 3228 break; 3229 default: 3230 /* Determination of which option table to search for to save time. */ 3231 if (!arg) 3232 return 0; 3233 3234 ptr_arg = strchr (arg, '='); 3235 3236 if (ptr_arg) 3237 { 3238 /* Find the value after '='. */ 3239 if (ptr_arg != NULL) 3240 ptr_arg++; 3241 for (coarse_tune = parse_opts; coarse_tune->name != NULL; coarse_tune++) 3242 { 3243 if (strncmp (arg, coarse_tune->name, (ptr_arg - arg)) == 0) 3244 { 3245 coarse_tune->func (ptr_arg); 3246 return 1; 3247 } 3248 } 3249 } 3250 else 3251 { 3252 int disable = 0; 3253 3254 /* Filter out the Disable option first. */ 3255 if (strncmp (arg, "no-", 3) == 0) 3256 { 3257 disable = 1; 3258 arg += 3; 3259 } 3260 3261 for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++) 3262 { 3263 if (strcmp (arg, fine_tune->name) == 0) 3264 { 3265 if (fine_tune->var != NULL) 3266 *fine_tune->var = (disable) ? 0 : 1; 3267 return 1; 3268 } 3269 } 3270 } 3271 /* Nothing match. */ 3272 return 0; 3273 } 3274 3275 return 1; 3276 } 3277 3278 /* tc_check_label */ 3279 3280 void 3281 nds32_check_label (symbolS *label ATTRIBUTE_UNUSED) 3282 { 3283 /* The code used to create BB is move to frob_label. 3284 They should go there. */ 3285 } 3286 3287 static void 3288 set_endian_little (int on) 3289 { 3290 target_big_endian = !on; 3291 } 3292 3293 /* These functions toggles the generation of 16-bit. First encounter signals 3294 the beginning of not generating 16-bit instructions and next encounter 3295 signals the restoring back to default behavior. */ 3296 3297 static void 3298 trigger_16bit (int trigger) 3299 { 3300 enable_16bit = trigger; 3301 } 3302 3303 static int backup_16bit_mode; 3304 static void 3305 restore_16bit (int no_use ATTRIBUTE_UNUSED) 3306 { 3307 enable_16bit = backup_16bit_mode; 3308 } 3309 3310 static void 3311 off_16bit (int no_use ATTRIBUTE_UNUSED) 3312 { 3313 backup_16bit_mode = enable_16bit; 3314 enable_16bit = 0; 3315 } 3316 3317 /* Built-in segments for small object. */ 3318 typedef struct nds32_seg_entryT 3319 { 3320 segT s; 3321 const char *name; 3322 flagword flags; 3323 } nds32_seg_entry; 3324 3325 nds32_seg_entry nds32_seg_table[] = 3326 { 3327 {NULL, ".sdata_f", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA 3328 | SEC_HAS_CONTENTS | SEC_SMALL_DATA}, 3329 {NULL, ".sdata_b", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA 3330 | SEC_HAS_CONTENTS | SEC_SMALL_DATA}, 3331 {NULL, ".sdata_h", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA 3332 | SEC_HAS_CONTENTS | SEC_SMALL_DATA}, 3333 {NULL, ".sdata_w", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA 3334 | SEC_HAS_CONTENTS | SEC_SMALL_DATA}, 3335 {NULL, ".sdata_d", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA 3336 | SEC_HAS_CONTENTS | SEC_SMALL_DATA}, 3337 {NULL, ".sbss_f", SEC_ALLOC | SEC_SMALL_DATA}, 3338 {NULL, ".sbss_b", SEC_ALLOC | SEC_SMALL_DATA}, 3339 {NULL, ".sbss_h", SEC_ALLOC | SEC_SMALL_DATA}, 3340 {NULL, ".sbss_w", SEC_ALLOC | SEC_SMALL_DATA}, 3341 {NULL, ".sbss_d", SEC_ALLOC | SEC_SMALL_DATA} 3342 }; 3343 3344 /* Indexes to nds32_seg_table[]. */ 3345 enum NDS32_SECTIONS_ENUM 3346 { 3347 SDATA_F_SECTION = 0, 3348 SDATA_B_SECTION = 1, 3349 SDATA_H_SECTION = 2, 3350 SDATA_W_SECTION = 3, 3351 SDATA_D_SECTION = 4, 3352 SBSS_F_SECTION = 5, 3353 SBSS_B_SECTION = 6, 3354 SBSS_H_SECTION = 7, 3355 SBSS_W_SECTION = 8, 3356 SBSS_D_SECTION = 9 3357 }; 3358 3359 /* The following code is borrowed from v850_seg. Revise this is needed. */ 3360 3361 static void 3362 do_nds32_seg (int i, subsegT sub) 3363 { 3364 nds32_seg_entry *seg = nds32_seg_table + i; 3365 3366 obj_elf_section_change_hook (); 3367 3368 if (seg->s != NULL) 3369 subseg_set (seg->s, sub); 3370 else 3371 { 3372 seg->s = subseg_new (seg->name, sub); 3373 if (OUTPUT_FLAVOR == bfd_target_elf_flavour) 3374 { 3375 bfd_set_section_flags (stdoutput, seg->s, seg->flags); 3376 if ((seg->flags & SEC_LOAD) == 0) 3377 seg_info (seg->s)->bss = 1; 3378 } 3379 } 3380 } 3381 3382 static void 3383 nds32_seg (int i) 3384 { 3385 subsegT sub = get_absolute_expression (); 3386 3387 do_nds32_seg (i, sub); 3388 demand_empty_rest_of_line (); 3389 } 3390 3391 /* Set if label adjustment is needed. I should not adjust .xbyte in dwarf. */ 3392 static symbolS *nds32_last_label; /* Last label for aligment. */ 3393 3394 /* This code is referred from D30V for adjust label to be with pedning 3395 aligment. For example, 3396 LBYTE: .byte 0x12 3397 LHALF: .half 0x12 3398 LWORD: .word 0x12 3399 Without this, the above label will not attatch to incoming data. */ 3400 3401 static void 3402 nds32_adjust_label (int n) 3403 { 3404 /* FIXME: I think adjust lable and alignment is 3405 the programmer's obligation. Saddly, VLSI team doesn't 3406 properly use .align for their test cases. 3407 So I re-implement cons_align and auto adjust labels, again. 3408 3409 I think d30v's implmentation is simple and good enough. */ 3410 3411 symbolS *label = nds32_last_label; 3412 nds32_last_label = NULL; 3413 3414 /* SEC_ALLOC is used to eliminate .debug_ sections. 3415 SEC_CODE is used to include section for ILM. */ 3416 if (((now_seg->flags & SEC_ALLOC) == 0 && (now_seg->flags & SEC_CODE) == 0) 3417 || strcmp (now_seg->name, ".eh_frame") == 0 3418 || strcmp (now_seg->name, ".gcc_except_table") == 0) 3419 return; 3420 3421 /* Only frag by alignment when needed. 3422 Otherwise, it will fail to optimize labels on 4-byte boundary. (bug8454) 3423 See md_convert_frag () and RELAX_SET_RELAXABLE (frag) for details. */ 3424 if (frag_now_fix () & ((1 << n) -1 )) 3425 { 3426 if (subseg_text_p (now_seg)) 3427 frag_align_code (n, 0); 3428 else 3429 frag_align (n, 0, 0); 3430 3431 /* Record the minimum alignment for this segment. */ 3432 record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER); 3433 } 3434 3435 if (label != NULL) 3436 { 3437 symbolS *sym; 3438 int label_seen = FALSE; 3439 struct frag *old_frag; 3440 valueT old_value, new_value; 3441 3442 gas_assert (S_GET_SEGMENT (label) == now_seg); 3443 3444 old_frag = symbol_get_frag (label); 3445 old_value = S_GET_VALUE (label); 3446 new_value = (valueT) frag_now_fix (); 3447 3448 /* Multiple labels may be on the same address. And the last symbol 3449 may not be a label at all, e.g., register name, external function names, 3450 so I have to track the last label in tc_frob_label instead of 3451 just using symbol_lastP. */ 3452 for (sym = symbol_lastP; sym != NULL; sym = symbol_previous (sym)) 3453 { 3454 if (symbol_get_frag (sym) == old_frag 3455 && S_GET_VALUE (sym) == old_value) 3456 { 3457 /* Warning HERE! */ 3458 label_seen = TRUE; 3459 symbol_set_frag (sym, frag_now); 3460 S_SET_VALUE (sym, new_value); 3461 } 3462 else if (label_seen && symbol_get_frag (sym) != old_frag) 3463 break; 3464 } 3465 } 3466 } 3467 3468 void 3469 nds32_cons_align (int size ATTRIBUTE_UNUSED) 3470 { 3471 /* Do nothing here. 3472 This is called before `md_flush_pending_output' is called by `cons'. 3473 3474 There are two things should be done for auto-adjust-label. 3475 1. Align data/instructions and adjust label to be attached to them. 3476 2. Clear auto-adjust state, so incommng data/instructions will not 3477 adjust the label. 3478 3479 For example, 3480 .byte 0x1 3481 .L0: 3482 .word 0x2 3483 .word 0x3 3484 in this case, '.word 0x2' will adjust the label, .L0, but '.word 0x3' should not. 3485 3486 I think `md_flush_pending_output' is a good place to clear the auto-adjust state, 3487 but it is also called by `cons' before this function. 3488 To simplify the code, instead of overriding .zero, .fill, .space, etc, 3489 I think we should just adjust label in `nds32_aligned_X_cons' instead of here. */ 3490 } 3491 3492 static void 3493 nds32_aligned_cons (int idx) 3494 { 3495 nds32_adjust_label (idx); 3496 /* Call default handler. */ 3497 cons (1 << idx); 3498 if (now_seg->flags & SEC_CODE 3499 && now_seg->flags & SEC_ALLOC && now_seg->flags & SEC_RELOC) 3500 { 3501 /* Use BFD_RELOC_NDS32_DATA to avoid EX9 optimization replacing data. */ 3502 expressionS exp; 3503 3504 exp.X_add_number = 0; 3505 exp.X_op = O_constant; 3506 fix_new_exp (frag_now, frag_now_fix () - (1 << idx), 1 << idx, 3507 &exp, 0, BFD_RELOC_NDS32_DATA); 3508 } 3509 } 3510 3511 /* `.double' directive. */ 3512 3513 static void 3514 nds32_aligned_float_cons (int type) 3515 { 3516 switch (type) 3517 { 3518 case 'f': 3519 case 'F': 3520 case 's': 3521 case 'S': 3522 nds32_adjust_label (2); 3523 break; 3524 case 'd': 3525 case 'D': 3526 case 'r': 3527 case 'R': 3528 nds32_adjust_label (4); 3529 break; 3530 default: 3531 as_bad ("Unrecognized float type, %c\n", (char)type); 3532 } 3533 /* Call default handler. */ 3534 float_cons (type); 3535 } 3536 3537 static void 3538 nds32_enable_pic (int ignore ATTRIBUTE_UNUSED) 3539 { 3540 /* Another way to do -mpic. 3541 This is for GCC internal use and should always be first line 3542 of code, otherwise, the effect is not determined. */ 3543 nds32_pic = 1; 3544 } 3545 3546 static void 3547 nds32_set_abi (int ver) 3548 { 3549 nds32_abi = ver; 3550 } 3551 3552 /* Relax directive to set relocation R_NDS32_RELAX_ENTRY value. */ 3553 3554 static void 3555 nds32_relax_relocs (int relax) 3556 { 3557 char saved_char; 3558 char *name; 3559 int i; 3560 char *subtype_relax[] = 3561 {"", "", "ex9", "ifc"}; 3562 3563 name = input_line_pointer; 3564 while (*input_line_pointer && !ISSPACE (*input_line_pointer)) 3565 input_line_pointer++; 3566 saved_char = *input_line_pointer; 3567 *input_line_pointer = 0; 3568 3569 for (i = 0; i < (int) ARRAY_SIZE (subtype_relax); i++) 3570 { 3571 if (strcmp (name, subtype_relax[i]) == 0) 3572 { 3573 switch (i) 3574 { 3575 case 0: 3576 case 1: 3577 enable_relax_relocs = relax & enable_relax_relocs; 3578 enable_relax_ex9 = relax & enable_relax_ex9; 3579 enable_relax_ifc = relax & enable_relax_ifc; 3580 break; 3581 case 2: 3582 enable_relax_ex9 = relax; 3583 break; 3584 case 3: 3585 enable_relax_ifc = relax; 3586 break; 3587 default: 3588 break; 3589 } 3590 break; 3591 } 3592 } 3593 *input_line_pointer = saved_char; 3594 ignore_rest_of_line (); 3595 } 3596 3597 /* Record which arguments register($r0 ~ $r5) is not used in callee. 3598 bit[i] for $ri */ 3599 3600 static void 3601 nds32_set_hint_func_args (int ignore ATTRIBUTE_UNUSED) 3602 { 3603 ignore_rest_of_line (); 3604 } 3605 3606 /* Insert relocations to mark the begin and end of a fp-omitted function, 3607 for further relaxation use. 3608 bit[i] for $ri */ 3609 3610 static void 3611 nds32_omit_fp_begin (int mode) 3612 { 3613 expressionS exp; 3614 3615 if (nds32_relax_fp_as_gp == 0) 3616 return; 3617 exp.X_op = O_symbol; 3618 exp.X_add_symbol = abs_section_sym; 3619 if (mode == 1) 3620 { 3621 in_omit_fp = 1; 3622 exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG; 3623 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0, 3624 BFD_RELOC_NDS32_RELAX_REGION_BEGIN); 3625 } 3626 else 3627 { 3628 in_omit_fp = 0; 3629 exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG; 3630 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0, 3631 BFD_RELOC_NDS32_RELAX_REGION_END); 3632 } 3633 } 3634 3635 /* Insert relocations to mark the begin and end of ex9 region, 3636 for further relaxation use. 3637 bit[i] for $ri */ 3638 3639 static void 3640 nds32_no_ex9_begin (int mode) 3641 { 3642 expressionS exp; 3643 3644 exp.X_op = O_symbol; 3645 exp.X_add_symbol = abs_section_sym; 3646 if (mode == 1) 3647 { 3648 exp.X_add_number = R_NDS32_RELAX_REGION_NO_EX9_FLAG; 3649 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0, 3650 BFD_RELOC_NDS32_RELAX_REGION_BEGIN); 3651 } 3652 else 3653 { 3654 exp.X_add_number = R_NDS32_RELAX_REGION_NO_EX9_FLAG; 3655 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0, 3656 BFD_RELOC_NDS32_RELAX_REGION_END); 3657 } 3658 } 3659 3660 static void 3661 nds32_loop_begin (int mode) 3662 { 3663 /* Insert loop region relocation here. */ 3664 expressionS exp; 3665 3666 exp.X_op = O_symbol; 3667 exp.X_add_symbol = abs_section_sym; 3668 if (mode == 1) 3669 { 3670 exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG; 3671 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0, 3672 BFD_RELOC_NDS32_RELAX_REGION_BEGIN); 3673 } 3674 else 3675 { 3676 exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG; 3677 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0, 3678 BFD_RELOC_NDS32_RELAX_REGION_END); 3679 } 3680 } 3681 3682 struct nds32_relocs_group 3683 { 3684 struct nds32_relocs_pattern *pattern; 3685 struct nds32_relocs_group *next; 3686 }; 3687 3688 static struct nds32_relocs_group *nds32_relax_hint_current = NULL; 3689 3690 /* Insert a relax hint. */ 3691 3692 static void 3693 nds32_relax_hint (int mode ATTRIBUTE_UNUSED) 3694 { 3695 char *name; 3696 char saved_char; 3697 struct nds32_relocs_pattern *relocs = NULL; 3698 struct nds32_relocs_group *group, *new; 3699 3700 name = input_line_pointer; 3701 while (*input_line_pointer && !ISSPACE (*input_line_pointer)) 3702 input_line_pointer++; 3703 saved_char = *input_line_pointer; 3704 *input_line_pointer = 0; 3705 name = strdup (name); 3706 3707 /* Find relax hint entry for next instruction, and all member will be 3708 initialized at that time. */ 3709 relocs = hash_find (nds32_hint_hash, name); 3710 if (relocs == NULL) 3711 { 3712 relocs = malloc (sizeof (struct nds32_relocs_pattern)); 3713 hash_insert (nds32_hint_hash, name, relocs); 3714 } 3715 else 3716 { 3717 while (relocs->next) 3718 relocs=relocs->next; 3719 relocs->next = malloc (sizeof (struct nds32_relocs_pattern)); 3720 relocs = relocs->next; 3721 } 3722 3723 relocs->next = NULL; 3724 *input_line_pointer = saved_char; 3725 ignore_rest_of_line (); 3726 3727 /* Get the final one of relax hint series. */ 3728 3729 /* It has to build this list because there are maybe more than one 3730 instructions relative to the same instruction. It to connect to 3731 next instruction after md_assemble. */ 3732 new = malloc (sizeof (struct nds32_relocs_group)); 3733 new->pattern = relocs; 3734 new->next = NULL; 3735 group = nds32_relax_hint_current; 3736 if (!group) 3737 nds32_relax_hint_current = new; 3738 else 3739 { 3740 while (group->next != NULL) 3741 group = group->next; 3742 group->next = new; 3743 } 3744 relaxing = TRUE; 3745 } 3746 3747 /* Decide the size of vector entries, only accepts 4 or 16 now. */ 3748 3749 static void 3750 nds32_vec_size (int ignore ATTRIBUTE_UNUSED) 3751 { 3752 expressionS exp; 3753 3754 expression (&exp); 3755 3756 if (exp.X_op == O_constant) 3757 { 3758 if (exp.X_add_number == 4 || exp.X_add_number == 16) 3759 { 3760 if (vec_size == 0) 3761 vec_size = exp.X_add_number; 3762 else if (vec_size != exp.X_add_number) 3763 as_warn (_("Different arguments of .vec_size are found, " 3764 "previous %d, current %d"), 3765 (int) vec_size, (int) exp.X_add_number); 3766 } 3767 else 3768 as_warn (_("Argument of .vec_size is expected 4 or 16, actual: %d."), 3769 (int) exp.X_add_number); 3770 } 3771 else 3772 as_warn (_("Argument of .vec_size is not a constant.")); 3773 } 3774 3775 /* The behavior of ".flag" directive varies depending on the target. 3776 In nds32 target, we use it to recognize whether this assembly content is 3777 generated by compiler. Other features can also be added in this function 3778 in the future. */ 3779 3780 static void 3781 nds32_flag (int ignore ATTRIBUTE_UNUSED) 3782 { 3783 char *name; 3784 char saved_char; 3785 int i; 3786 char *possible_flags[] = { "verbatim" }; 3787 3788 /* Skip whitespaces. */ 3789 name = input_line_pointer; 3790 while (*input_line_pointer && !ISSPACE (*input_line_pointer)) 3791 input_line_pointer++; 3792 saved_char = *input_line_pointer; 3793 *input_line_pointer = 0; 3794 3795 for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++) 3796 { 3797 if (strcmp (name, possible_flags[i]) == 0) 3798 { 3799 switch (i) 3800 { 3801 case 0: 3802 /* flag: verbatim */ 3803 verbatim = 1; 3804 break; 3805 default: 3806 break; 3807 } 3808 /* Already found the flag, no need to continue next loop. */ 3809 break; 3810 } 3811 } 3812 3813 *input_line_pointer = saved_char; 3814 ignore_rest_of_line (); 3815 } 3816 3817 static void 3818 nds32_n12hc (int ignore ATTRIBUTE_UNUSED) 3819 { 3820 /* N1213HC core is used. */ 3821 } 3822 3823 3824 /* The target specific pseudo-ops which we support. */ 3825 const pseudo_typeS md_pseudo_table[] = 3826 { 3827 /* Forced alignment if declared these ways. */ 3828 {"ascii", stringer, 8 + 0}, 3829 {"asciz", stringer, 8 + 1}, 3830 {"double", nds32_aligned_float_cons, 'd'}, 3831 {"dword", nds32_aligned_cons, 3}, 3832 {"float", nds32_aligned_float_cons, 'f'}, 3833 {"half", nds32_aligned_cons, 1}, 3834 {"hword", nds32_aligned_cons, 1}, 3835 {"int", nds32_aligned_cons, 2}, 3836 {"long", nds32_aligned_cons, 2}, 3837 {"octa", nds32_aligned_cons, 4}, 3838 {"quad", nds32_aligned_cons, 3}, 3839 {"qword", nds32_aligned_cons, 4}, 3840 {"short", nds32_aligned_cons, 1}, 3841 {"byte", nds32_aligned_cons, 0}, 3842 {"single", nds32_aligned_float_cons, 'f'}, 3843 {"string", stringer, 8 + 1}, 3844 {"word", nds32_aligned_cons, 2}, 3845 3846 {"little", set_endian_little, 1}, 3847 {"big", set_endian_little, 0}, 3848 {"16bit_on", trigger_16bit, 1}, 3849 {"16bit_off", trigger_16bit, 0}, 3850 {"restore_16bit", restore_16bit, 0}, 3851 {"off_16bit", off_16bit, 0}, 3852 3853 {"sdata_d", nds32_seg, SDATA_D_SECTION}, 3854 {"sdata_w", nds32_seg, SDATA_W_SECTION}, 3855 {"sdata_h", nds32_seg, SDATA_H_SECTION}, 3856 {"sdata_b", nds32_seg, SDATA_B_SECTION}, 3857 {"sdata_f", nds32_seg, SDATA_F_SECTION}, 3858 3859 {"sbss_d", nds32_seg, SBSS_D_SECTION}, 3860 {"sbss_w", nds32_seg, SBSS_W_SECTION}, 3861 {"sbss_h", nds32_seg, SBSS_H_SECTION}, 3862 {"sbss_b", nds32_seg, SBSS_B_SECTION}, 3863 {"sbss_f", nds32_seg, SBSS_F_SECTION}, 3864 3865 {"pic", nds32_enable_pic, 0}, 3866 {"n12_hc", nds32_n12hc, 0}, 3867 {"abi_1", nds32_set_abi, E_NDS_ABI_V1}, 3868 {"abi_2", nds32_set_abi, E_NDS_ABI_AABI}, 3869 /* Obsolete. */ 3870 {"abi_2fp", nds32_set_abi, E_NDS_ABI_V2FP}, 3871 {"abi_2fp_plus", nds32_set_abi, E_NDS_ABI_V2FP_PLUS}, 3872 {"relax", nds32_relax_relocs, 1}, 3873 {"no_relax", nds32_relax_relocs, 0}, 3874 {"hint_func_args", nds32_set_hint_func_args, 0}, /* Abandon?? */ 3875 {"omit_fp_begin", nds32_omit_fp_begin, 1}, 3876 {"omit_fp_end", nds32_omit_fp_begin, 0}, 3877 {"no_ex9_begin", nds32_no_ex9_begin, 1}, 3878 {"no_ex9_end", nds32_no_ex9_begin, 0}, 3879 {"vec_size", nds32_vec_size, 0}, 3880 {"flag", nds32_flag, 0}, 3881 {"innermost_loop_begin", nds32_loop_begin, 1}, 3882 {"innermost_loop_end", nds32_loop_begin, 0}, 3883 {"relax_hint", nds32_relax_hint, 0}, 3884 {NULL, NULL, 0} 3885 }; 3886 3887 void 3888 nds32_pre_do_align (int n, char *fill, int len, int max) 3889 { 3890 /* Only make a frag if we HAVE to... */ 3891 fragS *fragP; 3892 if (n != 0 && !need_pass_2) 3893 { 3894 if (fill == NULL) 3895 { 3896 if (subseg_text_p (now_seg)) 3897 { 3898 dwarf2_emit_insn (0); 3899 fragP = frag_now; 3900 frag_align_code (n, max); 3901 3902 /* Tag this alignment when there is a lable before it. */ 3903 if (label_exist) 3904 { 3905 fragP->tc_frag_data.flag = NDS32_FRAG_LABEL; 3906 label_exist = 0; 3907 } 3908 } 3909 else 3910 frag_align (n, 0, max); 3911 } 3912 else if (len <= 1) 3913 frag_align (n, *fill, max); 3914 else 3915 frag_align_pattern (n, fill, len, max); 3916 } 3917 } 3918 3919 void 3920 nds32_do_align (int n) 3921 { 3922 /* Optimize for space and label exists. */ 3923 expressionS exp; 3924 3925 /* FIXME:I think this will break debug info sections and except_table. */ 3926 if (!enable_relax_relocs || !subseg_text_p (now_seg)) 3927 return; 3928 3929 /* Create and attach a BFD_RELOC_NDS32_LABEL fixup 3930 the size of instruction may not be correct because 3931 it could be relaxable. */ 3932 exp.X_op = O_symbol; 3933 exp.X_add_symbol = section_symbol (now_seg); 3934 exp.X_add_number = n; 3935 fix_new_exp (frag_now, 3936 frag_now_fix (), 0, &exp, 0, BFD_RELOC_NDS32_LABEL); 3937 } 3938 3939 /* Supported Andes machines. */ 3940 struct nds32_machs 3941 { 3942 enum bfd_architecture bfd_mach; 3943 int mach_flags; 3944 }; 3945 3946 /* This is the callback for nds32-asm.c to parse operands. */ 3947 3948 int 3949 nds32_asm_parse_operand (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED, 3950 struct nds32_asm_insn *pinsn, 3951 char **pstr, int64_t *value) 3952 { 3953 char *hold; 3954 expressionS *pexp = pinsn->info; 3955 3956 hold = input_line_pointer; 3957 input_line_pointer = *pstr; 3958 expression (pexp); 3959 *pstr = input_line_pointer; 3960 input_line_pointer = hold; 3961 3962 switch (pexp->X_op) 3963 { 3964 case O_symbol: 3965 *value = 0; 3966 return NASM_R_SYMBOL; 3967 case O_constant: 3968 *value = pexp->X_add_number; 3969 return NASM_R_CONST; 3970 case O_illegal: 3971 case O_absent: 3972 case O_register: 3973 default: 3974 return NASM_R_ILLEGAL; 3975 } 3976 } 3977 3978 /* GAS will call this function at the start of the assembly, after the command 3979 line arguments have been parsed and all the machine independent 3980 initializations have been completed. */ 3981 3982 void 3983 md_begin (void) 3984 { 3985 struct nds32_keyword *k; 3986 relax_info_t *relax_info; 3987 3988 bfd_set_arch_mach (stdoutput, TARGET_ARCH, nds32_baseline); 3989 3990 nds32_init_nds32_pseudo_opcodes (); 3991 asm_desc.parse_operand = nds32_asm_parse_operand; 3992 nds32_asm_init (&asm_desc, 0); 3993 3994 /* Initial general pupose registers hash table. */ 3995 nds32_gprs_hash = hash_new (); 3996 for (k = keyword_gpr; k->name; k++) 3997 hash_insert (nds32_gprs_hash, k->name, k); 3998 3999 /* Initial branch hash table. */ 4000 nds32_relax_info_hash = hash_new (); 4001 for (relax_info = relax_table; relax_info->opcode; relax_info++) 4002 hash_insert (nds32_relax_info_hash, relax_info->opcode, relax_info); 4003 4004 /* Initial relax hint hash table. */ 4005 nds32_hint_hash = hash_new (); 4006 enable_16bit = nds32_16bit_ext; 4007 } 4008 4009 /* HANDLE_ALIGN in write.c. */ 4010 4011 void 4012 nds32_handle_align (fragS *fragp) 4013 { 4014 static const unsigned char nop16[] = { 0x92, 0x00 }; 4015 static const unsigned char nop32[] = { 0x40, 0x00, 0x00, 0x09 }; 4016 int bytes; 4017 char *p; 4018 4019 if (fragp->fr_type != rs_align_code) 4020 return; 4021 4022 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; 4023 p = fragp->fr_literal + fragp->fr_fix; 4024 4025 if (bytes & 1) 4026 { 4027 *p++ = 0; 4028 bytes--; 4029 } 4030 4031 if (bytes & 2) 4032 { 4033 expressionS exp_t; 4034 exp_t.X_op = O_symbol; 4035 exp_t.X_add_symbol = abs_section_sym; 4036 exp_t.X_add_number = R_NDS32_INSN16_CONVERT_FLAG; 4037 fix_new_exp (fragp, fragp->fr_fix, 2, &exp_t, 0, 4038 BFD_RELOC_NDS32_INSN16); 4039 memcpy (p, nop16, 2); 4040 p += 2; 4041 bytes -= 2; 4042 } 4043 4044 while (bytes >= 4) 4045 { 4046 memcpy (p, nop32, 4); 4047 p += 4; 4048 bytes -= 4; 4049 } 4050 4051 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; 4052 fragp->fr_fix += bytes; 4053 } 4054 4055 /* md_flush_pending_output */ 4056 4057 void 4058 nds32_flush_pending_output (void) 4059 { 4060 nds32_last_label = NULL; 4061 } 4062 4063 void 4064 nds32_frob_label (symbolS *label) 4065 { 4066 dwarf2_emit_label (label); 4067 } 4068 4069 /* TC_START_LABEL */ 4070 4071 int 4072 nds32_start_label (int asmdone ATTRIBUTE_UNUSED, int secdone ATTRIBUTE_UNUSED) 4073 { 4074 if (optimize && subseg_text_p (now_seg)) 4075 label_exist = 1; 4076 return 1; 4077 } 4078 4079 /* TARGET_FORMAT */ 4080 4081 const char * 4082 nds32_target_format (void) 4083 { 4084 #ifdef TE_LINUX 4085 if (target_big_endian) 4086 return "elf32-nds32be-linux"; 4087 else 4088 return "elf32-nds32le-linux"; 4089 #else 4090 if (target_big_endian) 4091 return "elf32-nds32be"; 4092 else 4093 return "elf32-nds32le"; 4094 #endif 4095 } 4096 4097 static enum nds32_br_range 4098 get_range_type (const struct nds32_field *field) 4099 { 4100 gas_assert (field != NULL); 4101 4102 if (field->bitpos != 0) 4103 return BR_RANGE_U4G; 4104 4105 if (field->bitsize == 24 && field->shift == 1) 4106 return BR_RANGE_S16M; 4107 else if (field->bitsize == 16 && field->shift == 1) 4108 return BR_RANGE_S64K; 4109 else if (field->bitsize == 14 && field->shift == 1) 4110 return BR_RANGE_S16K; 4111 else if (field->bitsize == 8 && field->shift == 1) 4112 return BR_RANGE_S256; 4113 else 4114 return BR_RANGE_U4G; 4115 } 4116 4117 /* Save pseudo instruction relocation list. */ 4118 4119 static struct nds32_relocs_pattern* 4120 nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_opcode *opcode, 4121 char *out, symbolS *sym, 4122 struct nds32_relocs_pattern *reloc_ptr, 4123 fragS *fragP) 4124 { 4125 if (!reloc_ptr) 4126 reloc_ptr = malloc (sizeof (struct nds32_relocs_pattern)); 4127 reloc_ptr->seg = now_seg; 4128 reloc_ptr->sym = sym; 4129 reloc_ptr->frag = fragP; 4130 reloc_ptr->frchain = frchain_now; 4131 reloc_ptr->fixP = fixP; 4132 reloc_ptr->opcode = opcode; 4133 reloc_ptr->where = out; 4134 reloc_ptr->next = NULL; 4135 return reloc_ptr; 4136 } 4137 4138 /* Check X_md to transform relocation. */ 4139 4140 static fixS* 4141 nds32_elf_record_fixup_exp (fragS *fragP, char *str, 4142 const struct nds32_field *fld, 4143 expressionS *pexp, char* out, 4144 struct nds32_asm_insn *insn) 4145 { 4146 int reloc = -1; 4147 expressionS exp; 4148 fixS *fixP = NULL; 4149 4150 /* Handle instruction relocation. */ 4151 if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_HI20)) 4152 { 4153 /* Relocation for hi20 modifier. */ 4154 switch (pexp->X_md) 4155 { 4156 case BFD_RELOC_NDS32_GOTOFF: /* @GOTOFF */ 4157 reloc = BFD_RELOC_NDS32_GOTOFF_HI20; 4158 break; 4159 case BFD_RELOC_NDS32_GOT20: /* @GOT */ 4160 reloc = BFD_RELOC_NDS32_GOT_HI20; 4161 break; 4162 case BFD_RELOC_NDS32_25_PLTREL: /* @PLT */ 4163 if (!nds32_pic) 4164 as_bad (_("Invalid PIC expression.")); 4165 else 4166 reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20; 4167 break; 4168 case BFD_RELOC_NDS32_GOTPC20: /* _GLOBAL_OFFSET_TABLE_ */ 4169 reloc = BFD_RELOC_NDS32_GOTPC_HI20; 4170 break; 4171 case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */ 4172 reloc = BFD_RELOC_NDS32_TLS_LE_HI20; 4173 break; 4174 case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */ 4175 reloc = BFD_RELOC_NDS32_TLS_IE_HI20; 4176 break; 4177 default: /* No suffix. */ 4178 reloc = BFD_RELOC_NDS32_HI20; 4179 break; 4180 } 4181 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, 4182 insn->info, 0 /* pcrel */, reloc); 4183 } 4184 else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_LO12)) 4185 { 4186 /* Relocation for lo12 modifier. */ 4187 if (fld->bitsize == 15 && fld->shift == 0) 4188 { 4189 /* [ls]bi || ori */ 4190 switch (pexp->X_md) 4191 { 4192 case BFD_RELOC_NDS32_GOTOFF: /* @GOTOFF */ 4193 reloc = BFD_RELOC_NDS32_GOTOFF_LO12; 4194 break; 4195 case BFD_RELOC_NDS32_GOT20: /* @GOT */ 4196 reloc = BFD_RELOC_NDS32_GOT_LO12; 4197 break; 4198 case BFD_RELOC_NDS32_25_PLTREL: /* @PLT */ 4199 if (!nds32_pic) 4200 as_bad (_("Invalid PIC expression.")); 4201 else 4202 reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12; 4203 break; 4204 case BFD_RELOC_NDS32_GOTPC20: /* _GLOBAL_OFFSET_TABLE_ */ 4205 reloc = BFD_RELOC_NDS32_GOTPC_LO12; 4206 break; 4207 case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */ 4208 reloc = BFD_RELOC_NDS32_TLS_LE_LO12; 4209 break; 4210 default: /* No suffix. */ 4211 reloc = BFD_RELOC_NDS32_LO12S0; 4212 break; 4213 } 4214 } 4215 else if (fld->bitsize == 15 && fld->shift == 1) 4216 reloc = BFD_RELOC_NDS32_LO12S1; /* [ls]hi */ 4217 else if (fld->bitsize == 15 && fld->shift == 2) 4218 { 4219 /* [ls]wi */ 4220 switch (pexp->X_md) 4221 { 4222 case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */ 4223 reloc = BFD_RELOC_NDS32_TLS_IE_LO12S2; 4224 break; 4225 default: /* No suffix. */ 4226 reloc = BFD_RELOC_NDS32_LO12S2; 4227 break; 4228 } 4229 } 4230 else if (fld->bitsize == 15 && fld->shift == 3) 4231 reloc = BFD_RELOC_NDS32_LO12S3; /* [ls]di */ 4232 else if (fld->bitsize == 12 && fld->shift == 2) 4233 reloc = R_NDS32_LO12S2_SP_RELA; /* f[ls][sd]i */ 4234 4235 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, 4236 insn->info, 0 /* pcrel */, reloc); 4237 } 4238 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4 4239 && (insn->attr & NASM_ATTR_PCREL)) 4240 { 4241 /* Relocation for 32-bit branch instructions. */ 4242 if (fld->bitsize == 24 && fld->shift == 1) 4243 reloc = BFD_RELOC_NDS32_25_PCREL; 4244 else if (fld->bitsize == 16 && fld->shift == 1) 4245 reloc = BFD_RELOC_NDS32_17_PCREL; 4246 else if (fld->bitsize == 14 && fld->shift == 1) 4247 reloc = BFD_RELOC_NDS32_15_PCREL; 4248 else if (fld->bitsize == 8 && fld->shift == 1) 4249 reloc = BFD_RELOC_NDS32_WORD_9_PCREL; 4250 else 4251 abort (); 4252 4253 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, 4254 insn->info, 1 /* pcrel */, reloc); 4255 } 4256 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4 4257 && (insn->attr & NASM_ATTR_GPREL)) 4258 { 4259 /* Relocation for 32-bit gp-relative instructions. */ 4260 if (fld->bitsize == 19 && fld->shift == 0) 4261 reloc = BFD_RELOC_NDS32_SDA19S0; 4262 else if (fld->bitsize == 18 && fld->shift == 1) 4263 reloc = BFD_RELOC_NDS32_SDA18S1; 4264 else if (fld->bitsize == 17 && fld->shift == 2) 4265 reloc = BFD_RELOC_NDS32_SDA17S2; 4266 else 4267 abort (); 4268 4269 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, 4270 insn->info, 0 /* pcrel */, reloc); 4271 /* Insert INSN16 for converting fp_as_gp. */ 4272 exp.X_op = O_symbol; 4273 exp.X_add_symbol = abs_section_sym; 4274 exp.X_add_number = 0; 4275 if (in_omit_fp && reloc == BFD_RELOC_NDS32_SDA17S2) 4276 fix_new_exp (fragP, out - fragP->fr_literal, 4277 insn->opcode->isize, &exp, 0 /* pcrel */, 4278 BFD_RELOC_NDS32_INSN16); 4279 } 4280 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 2 4281 && (insn->attr & NASM_ATTR_PCREL)) 4282 { 4283 /* Relocation for 16-bit branch instructions. */ 4284 if (fld->bitsize == 8 && fld->shift == 1) 4285 reloc = BFD_RELOC_NDS32_9_PCREL; 4286 else 4287 abort (); 4288 4289 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, 4290 insn->info, 1 /* pcrel */, reloc); 4291 } 4292 else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_IFC_EXT)) 4293 { 4294 /* Relocation for ifcall instruction. */ 4295 if (insn->opcode->isize == 2 && fld->bitsize == 9 && fld->shift == 1) 4296 reloc = BFD_RELOC_NDS32_10IFCU_PCREL; 4297 else if (insn->opcode->isize == 4 && fld->bitsize == 16 4298 && fld->shift == 1) 4299 reloc = BFD_RELOC_NDS32_17IFC_PCREL; 4300 else 4301 abort (); 4302 4303 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize, 4304 insn->info, 1 /* pcrel */, reloc); 4305 } 4306 else if (fld) 4307 as_bad (_("Don't know how to handle this field. %s"), str); 4308 4309 return fixP; 4310 } 4311 4312 /* Build instruction pattern to relax. There are two type group pattern 4313 including pseudo instruction and relax hint. */ 4314 4315 static void 4316 nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out, 4317 struct nds32_opcode *opcode, fragS *fragP, 4318 const struct nds32_field *fld) 4319 { 4320 struct nds32_relocs_pattern *reloc_ptr; 4321 struct nds32_relocs_group *group; 4322 symbolS *sym = NULL; 4323 4324 /* The expression may be used uninitialized. */ 4325 if (fld) 4326 sym = pexp->X_add_symbol; 4327 4328 if (pseudo_opcode) 4329 { 4330 /* Save instruction relation for pseudo instruction expanding pattern. */ 4331 reloc_ptr = nds32_elf_save_pseudo_pattern (fixP, opcode, out, sym, 4332 NULL, fragP); 4333 if (!relocs_list) 4334 relocs_list = reloc_ptr; 4335 else 4336 { 4337 struct nds32_relocs_pattern *temp = relocs_list; 4338 while (temp->next) 4339 temp = temp->next; 4340 temp->next = reloc_ptr; 4341 } 4342 } 4343 else if (nds32_relax_hint_current) 4344 { 4345 /* Save instruction relation by relax hint. */ 4346 group = nds32_relax_hint_current; 4347 while (group) 4348 { 4349 nds32_elf_save_pseudo_pattern (fixP, opcode, out, sym, 4350 group->pattern, fragP); 4351 group = group->next; 4352 free (nds32_relax_hint_current); 4353 nds32_relax_hint_current = group; 4354 } 4355 } 4356 4357 /* Set relaxing false only for relax_hint trigger it. */ 4358 if (!pseudo_opcode) 4359 relaxing = FALSE; 4360 } 4361 4362 #define N32_MEM_EXT(insn) ((N32_OP6_MEM << 25) | insn) 4363 4364 /* Relax pattern for link time relaxation. */ 4365 4366 static struct nds32_relax_hint_table relax_ls_table[] = 4367 { 4368 { 4369 /* Set address: la -> sethi ori. */ 4370 NDS32_RELAX_HINT_LA, /* main_type */ 4371 8, /* relax_code_size */ 4372 { 4373 OP6 (SETHI), 4374 OP6 (ORI), 4375 }, /* relax_code_seq */ 4376 { 4377 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, 4378 {4, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_INSN16} 4379 } /* relax_fixup */ 4380 }, 4381 { 4382 /* Set address: l.w -> sethi ori. */ 4383 NDS32_RELAX_HINT_LS, /* main_type */ 4384 8, /* relax_code_size */ 4385 { 4386 OP6 (SETHI), 4387 OP6 (LBI), 4388 }, /* relax_code_seq */ 4389 { 4390 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE}, 4391 {4, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_INSN16} 4392 } /* relax_fixup */ 4393 }, 4394 { 4395 0, 4396 0, 4397 {0}, 4398 {{0, 0 , 0, 0}} 4399 } 4400 }; 4401 4402 /* Since sethi loadstore relocation has to using next instruction to determine 4403 elimination itself or not, we have to return the next instruction range. */ 4404 4405 static int 4406 nds32_elf_sethi_range (struct nds32_relocs_pattern *pattern) 4407 { 4408 int range = 0; 4409 while (pattern) 4410 { 4411 switch (pattern->opcode->value) 4412 { 4413 case INSN_LBI: 4414 case INSN_SBI: 4415 case INSN_LBSI: 4416 case N32_MEM_EXT (N32_MEM_LB): 4417 case N32_MEM_EXT (N32_MEM_LBS): 4418 case N32_MEM_EXT (N32_MEM_SB): 4419 range = NDS32_LOADSTORE_BYTE; 4420 break; 4421 case INSN_LHI: 4422 case INSN_SHI: 4423 case INSN_LHSI: 4424 case N32_MEM_EXT (N32_MEM_LH): 4425 case N32_MEM_EXT (N32_MEM_LHS): 4426 case N32_MEM_EXT (N32_MEM_SH): 4427 range = NDS32_LOADSTORE_HALF; 4428 break; 4429 case INSN_LWI: 4430 case INSN_SWI: 4431 case N32_MEM_EXT (N32_MEM_LW): 4432 case N32_MEM_EXT (N32_MEM_SW): 4433 range = NDS32_LOADSTORE_WORD; 4434 break; 4435 case INSN_FLSI: 4436 case INSN_FSSI: 4437 range = NDS32_LOADSTORE_FLOAT_S; 4438 break; 4439 case INSN_FLDI: 4440 case INSN_FSDI: 4441 range = NDS32_LOADSTORE_FLOAT_D; 4442 break; 4443 case INSN_ORI: 4444 range = NDS32_LOADSTORE_IMM; 4445 break; 4446 default: 4447 range = NDS32_LOADSTORE_NONE; 4448 break; 4449 } 4450 if (range != NDS32_LOADSTORE_NONE) 4451 break; 4452 pattern = pattern->next; 4453 } 4454 return range; 4455 } 4456 4457 /* The args means: instruction size, the 1st instruction is converted to 16 or 4458 not, optimize option, 16 bit instruction is enable. */ 4459 #define SET_ADDEND(size, convertible, optimize, insn16_on) \ 4460 (((size) & 0xff) | ((convertible) ? 1 << 31 : 0) \ 4461 | ((optimize) ? 1<< 30 : 0) | (insn16_on ? 1 << 29 : 0)) 4462 4463 static void 4464 nds32_set_elf_flags_by_insn (struct nds32_asm_insn * insn) 4465 { 4466 /* Set E_NDS32_HAS_EXT_INST. */ 4467 if (insn->opcode->attr & NASM_ATTR_PERF_EXT) 4468 { 4469 if (nds32_perf_ext) 4470 nds32_elf_flags |= E_NDS32_HAS_EXT_INST; 4471 else 4472 as_bad (_("instruction %s requires enabling performance extension"), 4473 insn->opcode->opcode); 4474 } 4475 else if (insn->opcode->attr & NASM_ATTR_PERF2_EXT) 4476 { 4477 if (nds32_perf_ext2) 4478 nds32_elf_flags |= E_NDS32_HAS_EXT2_INST; 4479 else 4480 as_bad (_("instruction %s requires enabling performance extension II"), 4481 insn->opcode->opcode); 4482 } 4483 else if (insn->opcode->attr & NASM_ATTR_AUDIO_ISAEXT) 4484 { 4485 if (nds32_audio_ext) 4486 nds32_elf_flags |= E_NDS32_HAS_AUDIO_INST; 4487 else 4488 as_bad (_("instruction %s requires enabling AUDIO extension"), 4489 insn->opcode->opcode); 4490 } 4491 else if (insn->opcode->attr & NASM_ATTR_STR_EXT) 4492 { 4493 if (nds32_string_ext) 4494 nds32_elf_flags |= E_NDS32_HAS_STRING_INST; 4495 else 4496 as_bad (_("instruction %s requires enabling STRING extension"), 4497 insn->opcode->opcode); 4498 } 4499 else if ((insn->opcode->attr & NASM_ATTR_DIV) 4500 && (insn->opcode->attr & NASM_ATTR_DXREG)) 4501 { 4502 if (nds32_div && nds32_dx_regs) 4503 nds32_elf_flags |= E_NDS32_HAS_DIV_DX_INST; 4504 else 4505 as_bad (_("instruction %s requires enabling DIV & DX_REGS extension"), 4506 insn->opcode->opcode); 4507 } 4508 else if (insn->opcode->attr & NASM_ATTR_FPU) 4509 { 4510 if (nds32_fpu_sp_ext || nds32_fpu_dp_ext) 4511 { 4512 if (!(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST))) 4513 nds32_fpu_com = 1; 4514 } 4515 else 4516 as_bad (_("instruction %s requires enabling FPU extension"), 4517 insn->opcode->opcode); 4518 } 4519 else if (insn->opcode->attr & NASM_ATTR_FPU_SP_EXT) 4520 { 4521 if (nds32_fpu_sp_ext) 4522 nds32_elf_flags |= E_NDS32_HAS_FPU_INST; 4523 else 4524 as_bad (_("instruction %s requires enabling FPU_SP extension"), 4525 insn->opcode->opcode); 4526 } 4527 else if ((insn->opcode->attr & NASM_ATTR_FPU_SP_EXT) 4528 && (insn->opcode->attr & NASM_ATTR_MAC)) 4529 { 4530 if (nds32_fpu_sp_ext && nds32_mac) 4531 { 4532 nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST; 4533 nds32_elf_flags |= E_NDS32_HAS_FPU_INST; 4534 } 4535 else 4536 as_bad (_("instruction %s requires enabling FPU_MAC extension"), 4537 insn->opcode->opcode); 4538 } 4539 else if (insn->opcode->attr & NASM_ATTR_FPU_DP_EXT) 4540 { 4541 if (nds32_fpu_dp_ext) 4542 nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST; 4543 else 4544 as_bad (_("instruction %s requires enabling FPU_DP extension"), 4545 insn->opcode->opcode); 4546 } 4547 else if ((insn->opcode->attr & NASM_ATTR_FPU_DP_EXT) 4548 && (insn->opcode->attr & NASM_ATTR_MAC)) 4549 { 4550 if (nds32_fpu_dp_ext && nds32_mac) 4551 { 4552 nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST; 4553 nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST; 4554 } 4555 else 4556 as_bad (_("instruction %s requires enabling FPU_MAC extension"), 4557 insn->opcode->opcode); 4558 } 4559 /* TODO: FPU_BOTH */ 4560 else if ((insn->opcode->attr & NASM_ATTR_MAC) 4561 && (insn->opcode->attr & NASM_ATTR_DXREG)) 4562 { 4563 if (nds32_mac && nds32_dx_regs) 4564 nds32_elf_flags |= E_NDS32_HAS_MAC_DX_INST; 4565 else 4566 as_bad (_("instruction %s requires enabling DX_REGS extension"), 4567 insn->opcode->opcode); 4568 } 4569 /* TODO: for DX_REG set but not for MAC, DIV, AUDIO */ 4570 else if (insn->opcode->attr & NASM_ATTR_IFC_EXT) 4571 { 4572 nds32_elf_flags |= E_NDS32_HAS_IFC_INST; 4573 } 4574 /* TODO: E_NDS32_HAS_SATURATION_INST */ 4575 } 4576 4577 /* Flag for analysis relaxation type. */ 4578 4579 enum nds32_insn_type 4580 { 4581 N32_RELAX_SETHI = 1, 4582 N32_RELAX_BR = (1 << 1), 4583 N32_RELAX_LSI = (1 << 2), 4584 N32_RELAX_JUMP = (1 << 3), 4585 N32_RELAX_CALL = (1 << 4), 4586 N32_RELAX_ORI = (1 << 5), 4587 N32_RELAX_MEM = (1 << 6), 4588 N32_RELAX_MOVI = (1 << 7), 4589 }; 4590 4591 struct nds32_hint_map 4592 { 4593 bfd_reloc_code_real_type hi_type; 4594 char *opc; 4595 enum nds32_relax_hint_type hint_type; 4596 enum nds32_br_range range; 4597 enum nds32_insn_type insn_list; 4598 }; 4599 4600 /* Table to match instructions with hint and relax pattern. */ 4601 4602 static struct nds32_hint_map hint_map [] = 4603 { 4604 { 4605 /* LONGCALL4. */ 4606 BFD_RELOC_NDS32_HI20, 4607 "jal", 4608 NDS32_RELAX_HINT_NONE, 4609 BR_RANGE_U4G, 4610 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL 4611 }, 4612 { 4613 /* LONGCALL5. */ 4614 _dummy_first_bfd_reloc_code_real, 4615 "bgezal", 4616 NDS32_RELAX_HINT_NONE, 4617 BR_RANGE_S16M, 4618 N32_RELAX_BR | N32_RELAX_CALL 4619 }, 4620 { 4621 /* LONGCALL6. */ 4622 BFD_RELOC_NDS32_HI20, 4623 "bgezal", 4624 NDS32_RELAX_HINT_NONE, 4625 BR_RANGE_U4G, 4626 N32_RELAX_BR | N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL 4627 }, 4628 { 4629 /* LONGJUMP4. */ 4630 BFD_RELOC_NDS32_HI20, 4631 "j", 4632 NDS32_RELAX_HINT_NONE, 4633 BR_RANGE_U4G, 4634 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_JUMP 4635 }, 4636 { 4637 /* LONGJUMP5. */ 4638 /* There is two kinds of veriation of LONGJUMP5. One of them 4639 generate EMPTY relocation for converted INSN16 if needed. 4640 But we don't distinguish them here. */ 4641 _dummy_first_bfd_reloc_code_real, 4642 "beq", 4643 NDS32_RELAX_HINT_NONE, 4644 BR_RANGE_S16M, 4645 N32_RELAX_BR | N32_RELAX_JUMP 4646 }, 4647 { 4648 /* LONGJUMP6. */ 4649 BFD_RELOC_NDS32_HI20, 4650 "beq", 4651 NDS32_RELAX_HINT_NONE, 4652 BR_RANGE_U4G, 4653 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_BR | N32_RELAX_JUMP 4654 }, 4655 { 4656 /* LONGJUMP7. */ 4657 _dummy_first_bfd_reloc_code_real, 4658 "beqc", 4659 NDS32_RELAX_HINT_NONE, 4660 BR_RANGE_S16K, 4661 N32_RELAX_MOVI | N32_RELAX_BR 4662 }, 4663 { 4664 /* LOADSTORE ADDRESS. */ 4665 BFD_RELOC_NDS32_HI20, 4666 NULL, 4667 NDS32_RELAX_HINT_LA, 4668 BR_RANGE_U4G, 4669 N32_RELAX_SETHI | N32_RELAX_ORI 4670 }, 4671 { 4672 /* LOADSTORE ADDRESS. */ 4673 BFD_RELOC_NDS32_HI20, 4674 NULL, 4675 NDS32_RELAX_HINT_LS, 4676 BR_RANGE_U4G, 4677 N32_RELAX_SETHI | N32_RELAX_LSI 4678 }, 4679 {0, NULL, 0, 0 ,0} 4680 }; 4681 4682 /* Find the relaxation pattern according to instructions. */ 4683 4684 static bfd_boolean 4685 nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern, 4686 struct nds32_relax_hint_table *hint_info) 4687 { 4688 unsigned int opcode, seq_size; 4689 enum nds32_br_range range; 4690 struct nds32_relocs_pattern *pattern, *hi_pattern = NULL; 4691 char *opc = NULL; 4692 relax_info_t *relax_info = NULL; 4693 nds32_relax_fixup_info_t *fixup_info, *hint_fixup; 4694 enum nds32_relax_hint_type hint_type = NDS32_RELAX_HINT_NONE; 4695 struct nds32_relax_hint_table *table_ptr; 4696 uint32_t *code_seq, *hint_code; 4697 enum nds32_insn_type relax_type = 0; 4698 struct nds32_hint_map *map_ptr = hint_map; 4699 unsigned int i; 4700 char *check_insn[] = 4701 { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" }; 4702 4703 /* TODO: PLT GOT. */ 4704 /* Traverse all pattern instruction and set flag. */ 4705 pattern = relocs_pattern; 4706 while (pattern) 4707 { 4708 if (pattern->opcode->isize == 4) 4709 { 4710 /* 4 byte instruction. */ 4711 opcode = N32_OP6 (pattern->opcode->value); 4712 switch (opcode) 4713 { 4714 case N32_OP6_SETHI: 4715 hi_pattern = pattern; 4716 relax_type |= N32_RELAX_SETHI; 4717 break; 4718 case N32_OP6_MEM: 4719 relax_type |= N32_RELAX_MEM; 4720 break; 4721 case N32_OP6_ORI: 4722 relax_type |= N32_RELAX_ORI; 4723 break; 4724 case N32_OP6_BR1: 4725 case N32_OP6_BR2: 4726 case N32_OP6_BR3: 4727 relax_type |= N32_RELAX_BR; 4728 break; 4729 case N32_OP6_MOVI: 4730 relax_type |= N32_RELAX_MOVI; 4731 break; 4732 case N32_OP6_LBI: 4733 case N32_OP6_SBI: 4734 case N32_OP6_LBSI: 4735 case N32_OP6_LHI: 4736 case N32_OP6_SHI: 4737 case N32_OP6_LHSI: 4738 case N32_OP6_LWI: 4739 case N32_OP6_SWI: 4740 case N32_OP6_LWC: 4741 case N32_OP6_SWC: 4742 relax_type |= N32_RELAX_LSI; 4743 break; 4744 case N32_OP6_JREG: 4745 if (__GF (pattern->opcode->value, 0, 1) == 1) 4746 relax_type |= N32_RELAX_CALL; 4747 else 4748 relax_type |= N32_RELAX_JUMP; 4749 break; 4750 case N32_OP6_JI: 4751 if (__GF (pattern->opcode->value, 24, 1) == 1) 4752 relax_type |= N32_RELAX_CALL; 4753 else 4754 relax_type |= N32_RELAX_JUMP; 4755 break; 4756 default: 4757 as_warn (_("relax hint unrecognized instruction: line %d."), 4758 pattern->frag->fr_line); 4759 return FALSE; 4760 } 4761 } 4762 else 4763 { 4764 /* 2 byte instruction. Compare by opcode name because the opcode of 4765 2byte instruction is not regular. */ 4766 for (i = 0; i < sizeof (check_insn) / sizeof (check_insn[0]); i++) 4767 { 4768 if (strcmp (pattern->opcode->opcode, check_insn[i]) == 0) 4769 { 4770 relax_type |= N32_RELAX_BR; 4771 break; 4772 } 4773 } 4774 if (strcmp (pattern->opcode->opcode, "movi55") == 0) 4775 relax_type |= N32_RELAX_MOVI; 4776 } 4777 pattern = pattern->next; 4778 } 4779 4780 /* Analysis instruction flag to choose relaxation table. */ 4781 while (map_ptr->insn_list != 0) 4782 { 4783 if (map_ptr->insn_list == relax_type 4784 && (!hi_pattern 4785 || (hi_pattern->fixP 4786 && hi_pattern->fixP->fx_r_type == map_ptr->hi_type))) 4787 { 4788 opc = map_ptr->opc; 4789 hint_type = map_ptr->hint_type; 4790 range = map_ptr->range; 4791 break; 4792 } 4793 map_ptr++; 4794 } 4795 4796 if (map_ptr->insn_list == 0) 4797 { 4798 as_warn (_("Can not find match relax hint. line : %d"), 4799 relocs_pattern->frag->fr_line); 4800 return FALSE; 4801 } 4802 4803 /* Get the match table. */ 4804 if (opc) 4805 { 4806 /* Branch relax pattern. */ 4807 relax_info = hash_find (nds32_relax_info_hash, opc); 4808 if (!relax_info) 4809 return FALSE; 4810 fixup_info = relax_info->relax_fixup[range]; 4811 code_seq = relax_info->relax_code_seq[range]; 4812 seq_size = relax_info->relax_code_size[range]; 4813 } 4814 else if (hint_type) 4815 { 4816 /* Load-store relax pattern. */ 4817 table_ptr = relax_ls_table; 4818 while (table_ptr->main_type != 0) 4819 { 4820 if (table_ptr->main_type == hint_type) 4821 { 4822 fixup_info = table_ptr->relax_fixup; 4823 code_seq = table_ptr->relax_code_seq; 4824 seq_size = table_ptr->relax_code_size; 4825 break; 4826 } 4827 table_ptr++; 4828 } 4829 if (table_ptr->main_type == 0) 4830 return FALSE; 4831 } 4832 else 4833 return FALSE; 4834 4835 hint_fixup = hint_info->relax_fixup; 4836 hint_code = hint_info->relax_code_seq; 4837 hint_info->relax_code_size = seq_size; 4838 4839 while (fixup_info->size != 0) 4840 { 4841 if (fixup_info->ramp & NDS32_HINT) 4842 { 4843 memcpy (hint_fixup, fixup_info, sizeof (nds32_relax_fixup_info_t)); 4844 hint_fixup++; 4845 } 4846 fixup_info++; 4847 } 4848 /* Clear final relocation. */ 4849 memset (hint_fixup, 0, sizeof (nds32_relax_fixup_info_t)); 4850 /* Copy code sequance. */ 4851 memcpy (hint_code, code_seq, seq_size); 4852 return TRUE; 4853 } 4854 4855 /* Because there are a lot of variant of load-store, check 4856 all these type here. */ 4857 4858 #define CLEAN_REG(insn) ((insn) & 0xff0003ff) 4859 static bfd_boolean 4860 nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq) 4861 { 4862 char *check_insn[] = 4863 { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" }; 4864 uint32_t insn = opcode->value; 4865 unsigned int i; 4866 4867 insn = CLEAN_REG (opcode->value); 4868 if (insn == seq) 4869 return TRUE; 4870 4871 switch (seq) 4872 { 4873 case OP6 (LBI): 4874 /* In relocation_table, it regards instruction LBI as representation 4875 of all the NDS32_RELAX_HINT_LS pattern. */ 4876 if (insn == OP6 (LBI) || insn == OP6 (SBI) || insn == OP6 (LBSI) 4877 || insn == OP6 (LHI) || insn == OP6 (SHI) || insn == OP6 (LHSI) 4878 || insn == OP6 (LWI) || insn == OP6 (SWI) 4879 || insn == OP6 (LWC) || insn == OP6 (SWC)) 4880 return TRUE; 4881 break; 4882 case OP6 (BR2): 4883 /* This is for LONGCALL5 and LONGCALL6. */ 4884 if (insn == OP6 (BR2)) 4885 return TRUE; 4886 break; 4887 case OP6 (BR1): 4888 /* This is for LONGJUMP5 and LONGJUMP6. */ 4889 if (opcode->isize == 4 4890 && (insn == OP6 (BR1) || insn == OP6 (BR2) || insn == OP6 (BR3))) 4891 return TRUE; 4892 else if (opcode->isize == 2) 4893 { 4894 for (i = 0; i < sizeof (check_insn) / sizeof (check_insn[0]); i++) 4895 if (strcmp (opcode->opcode, check_insn[i]) == 0) 4896 return TRUE; 4897 } 4898 break; 4899 case OP6 (MOVI): 4900 /* This is for LONGJUMP7. */ 4901 if (opcode->isize == 2 && strcmp (opcode->opcode, "movi55") == 0) 4902 return TRUE; 4903 break; 4904 } 4905 return FALSE; 4906 } 4907 4908 /* Append relax relocation for link time relaxing. */ 4909 4910 static void 4911 nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value) 4912 { 4913 struct nds32_relocs_pattern *relocs_pattern = 4914 (struct nds32_relocs_pattern *) value; 4915 struct nds32_relocs_pattern *pattern_temp, *pattern_now; 4916 symbolS *sym, *hi_sym = NULL; 4917 expressionS exp; 4918 fragS *fragP; 4919 segT seg_bak = now_seg; 4920 frchainS *frchain_bak = frchain_now; 4921 struct nds32_relax_hint_table hint_info; 4922 nds32_relax_fixup_info_t *hint_fixup, *fixup_now; 4923 size_t fixup_size; 4924 offsetT branch_offset; 4925 fixS *fixP; 4926 int range, offset; 4927 unsigned int ptr_offset, hint_count, relax_code_size, count = 0; 4928 uint32_t *code_seq, code_insn; 4929 char *where; 4930 int pcrel; 4931 4932 if (!relocs_pattern) 4933 return; 4934 4935 if (!nds32_find_reloc_table (relocs_pattern, &hint_info)) 4936 return; 4937 4938 /* Save symbol for some EMPTY relocation using. */ 4939 pattern_now = relocs_pattern; 4940 while (pattern_now) 4941 { 4942 if (pattern_now->opcode->value == OP6 (SETHI)) 4943 { 4944 hi_sym = pattern_now->sym; 4945 break; 4946 } 4947 pattern_now = pattern_now->next; 4948 } 4949 4950 /* Inserting fix up must specify now_seg or frchain_now. */ 4951 now_seg = relocs_pattern->seg; 4952 frchain_now = relocs_pattern->frchain; 4953 fragP = relocs_pattern->frag; 4954 branch_offset = fragP->fr_offset; 4955 4956 hint_fixup = hint_info.relax_fixup; 4957 code_seq = hint_info.relax_code_seq; 4958 relax_code_size = hint_info.relax_code_size; 4959 pattern_now = relocs_pattern; 4960 4961 /* Insert relaxation. */ 4962 exp.X_op = O_symbol; 4963 4964 while (pattern_now) 4965 { 4966 /* Choose the match fixup by instruction. */ 4967 code_insn = CLEAN_REG (*(code_seq + count)); 4968 if (!nds32_match_hint_insn (pattern_now->opcode, code_insn)) 4969 { 4970 count = 0; 4971 code_insn = CLEAN_REG (*(code_seq + count)); 4972 4973 while (!nds32_match_hint_insn (pattern_now->opcode, code_insn)) 4974 { 4975 count++; 4976 if (count >= relax_code_size / 4) 4977 { 4978 as_bad (_("Internal error: Relax hint error. %s: %x"), 4979 now_seg->name, pattern_now->opcode->value); 4980 goto restore; 4981 } 4982 code_insn = CLEAN_REG (*(code_seq + count)); 4983 } 4984 } 4985 fragP = pattern_now->frag; 4986 sym = pattern_now->sym; 4987 branch_offset = fragP->fr_offset; 4988 offset = count * 4; 4989 where = pattern_now->where; 4990 /* Find the instruction map fix. */ 4991 fixup_now = hint_fixup; 4992 while (fixup_now->offset != offset) 4993 { 4994 fixup_now++; 4995 if (fixup_now->size == 0) 4996 break; 4997 } 4998 /* This element is without relaxation relocation. */ 4999 if (fixup_now->size == 0) 5000 { 5001 pattern_now = pattern_now->next; 5002 continue; 5003 } 5004 fixup_size = fixup_now->size; 5005 5006 /* Insert all fixup. */ 5007 while (fixup_size != 0 && fixup_now->offset == offset) 5008 { 5009 /* Set the real instruction size in element. */ 5010 fixup_size = pattern_now->opcode->isize; 5011 pcrel = ((fixup_now->ramp & NDS32_PCREL) != 0) ? 1 : 0; 5012 if (fixup_now->ramp & NDS32_FIX) 5013 { 5014 /* Convert original relocation. */ 5015 pattern_now->fixP->fx_r_type = fixup_now->r_type ; 5016 fixup_size = 0; 5017 } 5018 else if ((fixup_now->ramp & NDS32_PTR) != 0) 5019 { 5020 /* This relocation has to point to another instruction. Make 5021 sure each resolved relocation has to be pointed. */ 5022 pattern_temp = relocs_pattern; 5023 /* All instruction in relax_table should be 32-bit. */ 5024 hint_count = hint_info.relax_code_size / 4; 5025 code_insn = CLEAN_REG (*(code_seq + hint_count - 1)); 5026 while (pattern_temp) 5027 { 5028 /* Point to every resolved relocation. */ 5029 if (nds32_match_hint_insn (pattern_temp->opcode, code_insn)) 5030 { 5031 ptr_offset = 5032 pattern_temp->where - pattern_temp->frag->fr_literal; 5033 exp.X_add_symbol = symbol_temp_new (now_seg, ptr_offset, 5034 pattern_temp->frag); 5035 exp.X_add_number = 0; 5036 fixP = 5037 fix_new_exp (fragP, where - fragP->fr_literal, 5038 fixup_size, &exp, 0, fixup_now->r_type); 5039 fixP->fx_addnumber = fixP->fx_offset; 5040 } 5041 pattern_temp = pattern_temp->next; 5042 } 5043 fixup_size = 0; 5044 } 5045 else if (fixup_now->ramp & NDS32_ADDEND) 5046 { 5047 range = nds32_elf_sethi_range (relocs_pattern); 5048 if (range == NDS32_LOADSTORE_NONE) 5049 { 5050 as_bad (_("Internal error: Range error. %s"), now_seg->name); 5051 return; 5052 } 5053 exp.X_add_symbol = abs_section_sym; 5054 exp.X_add_number = SET_ADDEND (4, 0, optimize, enable_16bit); 5055 exp.X_add_number |= ((range & 0x3f) << 8); 5056 } 5057 else if ((fixup_now->ramp & NDS32_ABS) != 0) 5058 { 5059 /* This is a tag relocation. */ 5060 exp.X_add_symbol = abs_section_sym; 5061 exp.X_add_number = 0; 5062 } 5063 else if ((fixup_now->ramp & NDS32_INSN16) != 0) 5064 { 5065 if (!enable_16bit) 5066 fixup_size = 0; 5067 /* This is a tag relocation. */ 5068 exp.X_add_symbol = abs_section_sym; 5069 exp.X_add_number = 0; 5070 } 5071 else if ((fixup_now->ramp & NDS32_SYM) != 0) 5072 { 5073 /* For EMPTY relocation save the true symbol. */ 5074 exp.X_add_symbol = hi_sym; 5075 exp.X_add_number = branch_offset; 5076 } 5077 else 5078 { 5079 exp.X_add_symbol = sym; 5080 exp.X_add_number = branch_offset; 5081 } 5082 5083 if (fixup_size != 0) 5084 { 5085 fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size, 5086 &exp, pcrel, fixup_now->r_type); 5087 fixP->fx_addnumber = fixP->fx_offset; 5088 } 5089 fixup_now++; 5090 fixup_size = fixup_now->size; 5091 } 5092 if (count < relax_code_size / 4) 5093 count++; 5094 pattern_now = pattern_now->next; 5095 } 5096 5097 restore: 5098 now_seg = seg_bak; 5099 frchain_now = frchain_bak; 5100 } 5101 5102 /* Check instruction if it can be used for the baseline. */ 5103 5104 static bfd_boolean 5105 nds32_check_insn_available (struct nds32_asm_insn insn, char *str) 5106 { 5107 int attr = insn.attr & ATTR_ALL; 5108 static int baseline_isa = 0; 5109 /* No isa setting or all isa can use. */ 5110 if (attr == 0 || attr == ATTR_ALL) 5111 return TRUE; 5112 5113 if (baseline_isa == 0) 5114 { 5115 /* Map option baseline and instruction attribute. */ 5116 switch (nds32_baseline) 5117 { 5118 case ISA_V2: 5119 baseline_isa = ATTR (ISA_V2); 5120 break; 5121 case ISA_V3: 5122 baseline_isa = ATTR (ISA_V3); 5123 break; 5124 case ISA_V3M: 5125 baseline_isa = ATTR (ISA_V3M); 5126 break; 5127 } 5128 } 5129 5130 if ((baseline_isa & attr) == 0) 5131 { 5132 as_bad (_("Not support instrcution %s in the baseline."), str); 5133 return FALSE; 5134 } 5135 return TRUE; 5136 } 5137 5138 /* Stub of machine dependent. */ 5139 5140 void 5141 md_assemble (char *str) 5142 { 5143 struct nds32_asm_insn insn; 5144 char *out; 5145 struct nds32_pseudo_opcode *popcode; 5146 const struct nds32_field *fld = NULL; 5147 fixS *fixP; 5148 uint16_t insn_16; 5149 struct nds32_relocs_pattern *relocs_temp; 5150 expressionS *pexp; 5151 fragS *fragP; 5152 int label = label_exist; 5153 5154 popcode = nds32_lookup_pseudo_opcode (str); 5155 /* Note that we need to check 'verbatim' and 5156 'opcode->physical_op'. If the assembly content is generated by 5157 compiler and this opcode is a physical instruction, there is no 5158 need to perform pseudo instruction expansion/transformation. */ 5159 if (popcode && !(verbatim && popcode->physical_op)) 5160 { 5161 pseudo_opcode = TRUE; 5162 nds32_pseudo_opcode_wrapper (str, popcode); 5163 pseudo_opcode = FALSE; 5164 nds32_elf_append_relax_relocs (NULL, relocs_list); 5165 5166 /* Free pseudo list. */ 5167 relocs_temp = relocs_list; 5168 while (relocs_temp) 5169 { 5170 relocs_list = relocs_list->next; 5171 free (relocs_temp); 5172 relocs_temp = relocs_list; 5173 } 5174 5175 return; 5176 } 5177 5178 label_exist = 0; 5179 insn.info = (expressionS *) alloca (sizeof (expressionS)); 5180 asm_desc.result = NASM_OK; 5181 nds32_assemble (&asm_desc, &insn, str); 5182 5183 switch (asm_desc.result) 5184 { 5185 case NASM_ERR_UNKNOWN_OP: 5186 as_bad (_("Unrecognized opcode, %s."), str); 5187 return; 5188 case NASM_ERR_SYNTAX: 5189 as_bad (_("Incorrect syntax, %s."), str); 5190 return; 5191 case NASM_ERR_OPERAND: 5192 as_bad (_("Unrecognized operand/register, %s."), str); 5193 return; 5194 case NASM_ERR_OUT_OF_RANGE: 5195 as_bad (_("Operand out of range, %s."), str); 5196 return; 5197 case NASM_ERR_REG_REDUCED: 5198 as_bad (_("Prohibited register used for reduced-register, %s."), str); 5199 return; 5200 case NASM_ERR_JUNK_EOL: 5201 as_bad (_("Junk at end of line, %s."), str); 5202 return; 5203 } 5204 5205 gas_assert (insn.opcode); 5206 5207 nds32_set_elf_flags_by_insn (&insn); 5208 5209 gas_assert (insn.opcode->isize == 4 || insn.opcode->isize == 2); 5210 5211 if (!nds32_check_insn_available (insn, str)) 5212 return; 5213 5214 /* Make sure the begining of text being 2-byte align. */ 5215 nds32_adjust_label (1); 5216 fld = insn.field; 5217 /* Try to allocate the max size to guarantee relaxable same branch 5218 instructions in the same fragment. */ 5219 frag_grow (NDS32_MAXCHAR); 5220 fragP = frag_now; 5221 if (fld && (insn.attr & NASM_ATTR_BRANCH) 5222 && (pseudo_opcode || (insn.opcode->value != INSN_JAL 5223 && insn.opcode->value != INSN_J)) 5224 && (!verbatim || pseudo_opcode)) 5225 { 5226 /* User assembly code branch relax for it. */ 5227 /* If fld is not NULL, it is a symbol. */ 5228 /* Branch msut relax to proper pattern in user assembly code exclude 5229 J and JAL. Keep these two in original type for users which wants 5230 to keep their size be fixed. In general, assembler does not convert 5231 instruction generated by compiler. But jump instruction may be 5232 truncated in text virtual model. For workaround, compiler generate 5233 pseudo jump to fix this issue currently. */ 5234 5235 /* Get branch range type. */ 5236 dwarf2_emit_insn (0); 5237 enum nds32_br_range range_type; 5238 5239 pexp = insn.info; 5240 range_type = get_range_type (fld); 5241 5242 out = frag_var (rs_machine_dependent, NDS32_MAXCHAR, 5243 0, /* VAR is un-used. */ 5244 range_type, /* SUBTYPE is used as range type. */ 5245 pexp->X_add_symbol, pexp->X_add_number, 0); 5246 5247 fragP->fr_fix += insn.opcode->isize; 5248 fragP->tc_frag_data.opcode = insn.opcode; 5249 fragP->tc_frag_data.insn = insn.insn; 5250 if (insn.opcode->isize == 4) 5251 bfd_putb32 (insn.insn, out); 5252 else if (insn.opcode->isize == 2) 5253 bfd_putb16 (insn.insn, out); 5254 fragP->tc_frag_data.flag |= NDS32_FRAG_BRANCH; 5255 return; 5256 /* md_convert_frag will insert relocations. */ 5257 } 5258 else if (!relaxing && enable_16bit && (optimize || optimize_for_space) 5259 && ((!fld && !verbatim && insn.opcode->isize == 4 5260 && nds32_convert_32_to_16 (stdoutput, insn.insn, &insn_16, NULL)) 5261 || (insn.opcode->isize == 2 5262 && nds32_convert_16_to_32 (stdoutput, insn.insn, NULL)))) 5263 { 5264 /* Record this one is relaxable. */ 5265 pexp = insn.info; 5266 dwarf2_emit_insn (0); 5267 if (fld) 5268 { 5269 out = frag_var (rs_machine_dependent, 5270 4, /* Max size is 32-bit instruction. */ 5271 0, /* VAR is un-used. */ 5272 0, pexp->X_add_symbol, pexp->X_add_number, 0); 5273 fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE_BRANCH; 5274 } 5275 else 5276 out = frag_var (rs_machine_dependent, 5277 4, /* Max size is 32-bit instruction. */ 5278 0, /* VAR is un-used. */ 5279 0, NULL, 0, NULL); 5280 fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE; 5281 fragP->tc_frag_data.opcode = insn.opcode; 5282 fragP->tc_frag_data.insn = insn.insn; 5283 fragP->fr_fix += 2; 5284 5285 /* In original, we don't relax the instrucion with label on it, 5286 but this may cause some redundant nop16. Therefore, tag this 5287 relaxable instruction and relax it carefully. */ 5288 if (label) 5289 fragP->tc_frag_data.flag |= NDS32_FRAG_LABEL; 5290 5291 if (insn.opcode->isize == 4) 5292 bfd_putb16 (insn_16, out); 5293 else if (insn.opcode->isize == 2) 5294 bfd_putb16 (insn.insn, out); 5295 return; 5296 } 5297 else if ((verbatim || !relaxing) && optimize && label) 5298 { 5299 /* This instruction is with label. */ 5300 expressionS exp; 5301 out = frag_var (rs_machine_dependent, insn.opcode->isize, 5302 0, 0, NULL, 0, NULL); 5303 /* If this insturction is branch target, it is not relaxable. */ 5304 fragP->tc_frag_data.flag = NDS32_FRAG_LABEL; 5305 fragP->tc_frag_data.opcode = insn.opcode; 5306 fragP->tc_frag_data.insn = insn.insn; 5307 fragP->fr_fix += insn.opcode->isize; 5308 if (insn.opcode->isize == 4) 5309 { 5310 exp.X_op = O_symbol; 5311 exp.X_add_symbol = abs_section_sym; 5312 exp.X_add_number = 0; 5313 fixP = fix_new_exp (fragP, fragP->fr_fix - 4, 0, &exp, 5314 0, BFD_RELOC_NDS32_LABEL); 5315 if (!verbatim) 5316 fragP->tc_frag_data.flag = NDS32_FRAG_ALIGN; 5317 } 5318 } 5319 else 5320 out = frag_more (insn.opcode->isize); 5321 5322 if (insn.opcode->isize == 4) 5323 bfd_putb32 (insn.insn, out); 5324 if (insn.opcode->isize == 2) 5325 bfd_putb16 (insn.insn, out); 5326 5327 dwarf2_emit_insn (insn.opcode->isize); 5328 5329 /* Compiler generating code and user assembly pseudo load-store, insert 5330 fixup here. */ 5331 pexp = insn.info; 5332 fixP = nds32_elf_record_fixup_exp (fragP, str, fld, pexp, out, &insn); 5333 /* Build relaxation pattern when relaxing is enable. */ 5334 if (relaxing) 5335 nds32_elf_build_relax_relation (fixP, pexp, out, insn.opcode, fragP, fld); 5336 } 5337 5338 /* md_macro_start */ 5339 5340 void 5341 nds32_macro_start (void) 5342 { 5343 } 5344 5345 /* md_macro_info */ 5346 5347 void 5348 nds32_macro_info (void *info ATTRIBUTE_UNUSED) 5349 { 5350 } 5351 5352 /* md_macro_end */ 5353 5354 void 5355 nds32_macro_end (void) 5356 { 5357 } 5358 5359 /* GAS will call this function with one argument, an expressionS pointer, for 5360 any expression that can not be recognized. When the function is called, 5361 input_line_pointer will point to the start of the expression. */ 5362 5363 void 5364 md_operand (expressionS *expressionP) 5365 { 5366 if (*input_line_pointer == '#') 5367 { 5368 input_line_pointer++; 5369 expression (expressionP); 5370 } 5371 } 5372 5373 /* GAS will call this function for each section at the end of the assembly, to 5374 permit the CPU back end to adjust the alignment of a section. The function 5375 must take two arguments, a segT for the section and a valueT for the size of 5376 the section, and return a valueT for the rounded size. */ 5377 5378 valueT 5379 md_section_align (segT segment, valueT size) 5380 { 5381 int align = bfd_get_section_alignment (stdoutput, segment); 5382 5383 return ((size + (1 << align) - 1) & -(1 << align)); 5384 } 5385 5386 /* GAS will call this function when a symbol table lookup fails, before it 5387 creates a new symbol. Typically this would be used to supply symbols whose 5388 name or value changes dynamically, possibly in a context sensitive way. 5389 Predefined symbols with fixed values, such as register names or condition 5390 codes, are typically entered directly into the symbol table when md_begin 5391 is called. One argument is passed, a char * for the symbol. */ 5392 5393 symbolS * 5394 md_undefined_symbol (char *name ATTRIBUTE_UNUSED) 5395 { 5396 return NULL; 5397 } 5398 5399 static long 5400 nds32_calc_branch_offset (segT segment, fragS *fragP, 5401 long stretch ATTRIBUTE_UNUSED, 5402 relax_info_t *relax_info, 5403 enum nds32_br_range branch_range_type) 5404 { 5405 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode; 5406 symbolS *branch_symbol = fragP->fr_symbol; 5407 offsetT branch_offset = fragP->fr_offset; 5408 offsetT branch_target_address; 5409 offsetT branch_insn_address; 5410 long offset = 0; 5411 5412 if ((S_GET_SEGMENT (branch_symbol) != segment) 5413 || S_IS_WEAK (branch_symbol)) 5414 { 5415 /* The symbol is not in the SEGMENT. It could be far far away. */ 5416 offset = 0x80000000; 5417 } 5418 else 5419 { 5420 /* Calculate symbol-to-instruction offset. */ 5421 branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset; 5422 /* If the destination symbol is beyond current frag address, 5423 STRETCH will take effect to symbol's position. */ 5424 if (S_GET_VALUE (branch_symbol) > fragP->fr_address) 5425 branch_target_address += stretch; 5426 5427 branch_insn_address = fragP->fr_address + fragP->fr_fix; 5428 branch_insn_address -= opcode->isize; 5429 5430 /* Update BRANCH_INSN_ADDRESS to relaxed position. */ 5431 branch_insn_address += (relax_info->relax_code_size[branch_range_type] 5432 - relax_info->relax_branch_isize[branch_range_type]); 5433 5434 offset = branch_target_address - branch_insn_address; 5435 } 5436 5437 return offset; 5438 } 5439 5440 static enum nds32_br_range 5441 nds32_convert_to_range_type (long offset) 5442 { 5443 enum nds32_br_range range_type; 5444 5445 if (-(0x100) <= offset && offset < 0x100) /* 256 bytes */ 5446 range_type = BR_RANGE_S256; 5447 else if (-(0x4000) <= offset && offset < 0x4000) /* 16K bytes */ 5448 range_type = BR_RANGE_S16K; 5449 else if (-(0x10000) <= offset && offset < 0x10000) /* 64K bytes */ 5450 range_type = BR_RANGE_S64K; 5451 else if (-(0x1000000) <= offset && offset < 0x1000000) /* 16M bytes */ 5452 range_type = BR_RANGE_S16M; 5453 else /* 4G bytes */ 5454 range_type = BR_RANGE_U4G; 5455 5456 return range_type; 5457 } 5458 5459 /* Set insntruction register mask. */ 5460 5461 static void 5462 nds32_elf_get_set_cond (relax_info_t *relax_info, int offset, uint32_t *insn, 5463 uint32_t ori_insn, int range) 5464 { 5465 nds32_cond_field_t *cond_fields = relax_info->cond_field; 5466 nds32_cond_field_t *code_seq_cond = relax_info->relax_code_condition[range]; 5467 uint32_t mask; 5468 int i = 0; 5469 5470 /* The instruction has conditions. Collect condition values. */ 5471 while (code_seq_cond[i].bitmask != 0) 5472 { 5473 if (offset == code_seq_cond[i].offset) 5474 { 5475 mask = (ori_insn >> cond_fields[i].bitpos) & cond_fields[i].bitmask; 5476 /* Sign extend. */ 5477 if (cond_fields[i].signed_extend) 5478 mask = (mask ^ ((cond_fields[i].bitmask + 1) >> 1)) - 5479 ((cond_fields[i].bitmask + 1) >> 1); 5480 *insn |= (mask & code_seq_cond[i].bitmask) << code_seq_cond[i].bitpos; 5481 } 5482 i++; 5483 } 5484 } 5485 5486 5487 static int 5488 nds32_relax_branch_instructions (segT segment, fragS *fragP, 5489 long stretch ATTRIBUTE_UNUSED, 5490 int init) 5491 { 5492 enum nds32_br_range branch_range_type; 5493 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode; 5494 long offset = 0; 5495 enum nds32_br_range real_range_type; 5496 int adjust = 0; 5497 relax_info_t *relax_info; 5498 int diff = 0; 5499 int i, j, k; 5500 int code_seq_size; 5501 uint32_t *code_seq; 5502 uint32_t insn; 5503 int insn_size; 5504 int code_seq_offset; 5505 5506 /* Replace with gas_assert (fragP->fr_symbol != NULL); */ 5507 if (fragP->fr_symbol == NULL) 5508 return adjust; 5509 5510 /* If frag_var is not enough room, the previos frag is fr_full and with 5511 opcode. The new one is rs_dependent but without opcode. */ 5512 if (opcode == NULL) 5513 return adjust; 5514 5515 relax_info = hash_find (nds32_relax_info_hash, opcode->opcode); 5516 5517 if (relax_info == NULL) 5518 return adjust; 5519 5520 if (init) 5521 branch_range_type = relax_info->br_range; 5522 else 5523 branch_range_type = fragP->fr_subtype; 5524 5525 offset = nds32_calc_branch_offset (segment, fragP, stretch, 5526 relax_info, branch_range_type); 5527 5528 real_range_type = nds32_convert_to_range_type (offset); 5529 5530 /* If actual range is equal to instruction jump range, do nothing. */ 5531 if (real_range_type == branch_range_type) 5532 return adjust; 5533 5534 /* Find out proper relaxation code sequence. */ 5535 for (i = BR_RANGE_S256; i < BR_RANGE_NUM; i++) 5536 { 5537 if (real_range_type <= (unsigned int) i) 5538 { 5539 if (init) 5540 diff = relax_info->relax_code_size[i] - opcode->isize; 5541 else 5542 diff = relax_info->relax_code_size[i] 5543 - relax_info->relax_code_size[branch_range_type]; 5544 5545 /* If the instruction could be converted to 16-bits, 5546 minus the difference. */ 5547 code_seq_offset = 0; 5548 j = 0; 5549 k = 0; 5550 code_seq_size = relax_info->relax_code_size[i]; 5551 code_seq = relax_info->relax_code_seq[i]; 5552 while (code_seq_offset < code_seq_size) 5553 { 5554 insn = code_seq[j]; 5555 if (insn & 0x80000000) /* 16-bits instruction. */ 5556 { 5557 insn_size = 2; 5558 } 5559 else /* 32-bits instruction. */ 5560 { 5561 insn_size = 4; 5562 5563 while (relax_info->relax_fixup[i][k].size !=0 5564 && relax_info->relax_fixup[i][k].offset < code_seq_offset) 5565 k++; 5566 } 5567 5568 code_seq_offset += insn_size; 5569 j++; 5570 } 5571 5572 /* Update fr_subtype to new NDS32_BR_RANGE. */ 5573 fragP->fr_subtype = i; 5574 break; 5575 } 5576 } 5577 5578 return diff + adjust; 5579 } 5580 5581 /* Adjust relaxable frag till current frag. */ 5582 5583 static int 5584 nds32_adjust_relaxable_frag (fragS *startP, fragS *fragP) 5585 { 5586 int adj; 5587 if (startP->tc_frag_data.flag & NDS32_FRAG_RELAXED) 5588 adj = -2; 5589 else 5590 adj = 2; 5591 5592 startP->tc_frag_data.flag ^= NDS32_FRAG_RELAXED; 5593 5594 while (startP) 5595 { 5596 startP = startP->fr_next; 5597 if (startP) 5598 { 5599 startP->fr_address += adj; 5600 if (startP == fragP) 5601 break; 5602 } 5603 } 5604 return adj; 5605 } 5606 5607 static addressT 5608 nds32_get_align (addressT address, int align) 5609 { 5610 addressT mask, new_address; 5611 5612 mask = ~((~0) << align); 5613 new_address = (address + mask) & (~mask); 5614 return (new_address - address); 5615 } 5616 5617 /* Check the prev_frag is legal. */ 5618 static void 5619 invalid_prev_frag (fragS * fragP, fragS **prev_frag) 5620 { 5621 addressT address; 5622 fragS *frag_start = *prev_frag; 5623 5624 if (!frag_start) 5625 return; 5626 5627 if (frag_start->last_fr_address >= fragP->last_fr_address) 5628 { 5629 *prev_frag = NULL; 5630 return; 5631 } 5632 5633 fragS *frag_t = *prev_frag; 5634 while (frag_t != fragP) 5635 { 5636 if (frag_t->fr_type == rs_align 5637 || frag_t->fr_type == rs_align_code 5638 || frag_t->fr_type == rs_align_test) 5639 { 5640 /* Relax instruction can not walk across lable. */ 5641 if (frag_t->tc_frag_data.flag & NDS32_FRAG_LABEL) 5642 { 5643 prev_frag = NULL; 5644 return; 5645 } 5646 /* Relax previos relaxable to align rs_align frag. */ 5647 address = frag_t->fr_address + frag_t->fr_fix; 5648 addressT offset = nds32_get_align (address, (int) frag_t->fr_offset); 5649 if (offset & 0x2) 5650 { 5651 /* If there is label on the prev_frag, check if it is aligned. */ 5652 if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL) 5653 || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 ) 5654 & 0x2) == 0) 5655 nds32_adjust_relaxable_frag (*prev_frag, frag_t); 5656 } 5657 *prev_frag = NULL; 5658 return; 5659 } 5660 frag_t = frag_t->fr_next; 5661 } 5662 5663 if (fragP->tc_frag_data.flag & NDS32_FRAG_ALIGN) 5664 { 5665 address = fragP->fr_address; 5666 addressT offset = nds32_get_align (address, 2); 5667 if (offset & 0x2) 5668 { 5669 /* If there is label on the prev_frag, check if it is aligned. */ 5670 if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL) 5671 || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 ) 5672 & 0x2) == 0) 5673 nds32_adjust_relaxable_frag (*prev_frag, fragP); 5674 } 5675 *prev_frag = NULL; 5676 return; 5677 } 5678 } 5679 5680 /* md_relax_frag */ 5681 5682 int 5683 nds32_relax_frag (segT segment, fragS *fragP, long stretch ATTRIBUTE_UNUSED) 5684 { 5685 /* Currently, there are two kinds of relaxation in nds32 assembler. 5686 1. relax for branch 5687 2. relax for 32-bits to 16-bits */ 5688 5689 static fragS *prev_frag = NULL; 5690 int adjust = 0; 5691 5692 invalid_prev_frag (fragP, &prev_frag); 5693 5694 if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH) 5695 adjust = nds32_relax_branch_instructions (segment, fragP, stretch, 0); 5696 if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL) 5697 prev_frag = NULL; 5698 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE 5699 && (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) == 0) 5700 /* Here is considered relaxed case originally. But it may cause 5701 unendless loop when relaxing. Once the instruction is relaxed, 5702 it can not be undo. */ 5703 prev_frag = fragP; 5704 5705 return adjust; 5706 } 5707 5708 /* This function returns an initial guess of the length by which a fragment 5709 must grow to hold a branch to reach its destination. Also updates 5710 fr_type/fr_subtype as necessary. 5711 5712 It is called just before doing relaxation. Any symbol that is now undefined 5713 will not become defined. The guess for fr_var is ACTUALLY the growth beyond 5714 fr_fix. Whatever we do to grow fr_fix or fr_var contributes to our returned 5715 value. Although it may not be explicit in the frag, pretend fr_var starts 5716 with a 0 value. */ 5717 5718 int 5719 md_estimate_size_before_relax (fragS *fragP, segT segment) 5720 { 5721 /* Currently, there are two kinds of relaxation in nds32 assembler. 5722 1. relax for branch 5723 2. relax for 32-bits to 16-bits */ 5724 5725 /* Save previos relaxable frag. */ 5726 static fragS *prev_frag = NULL; 5727 int adjust = 0; 5728 5729 invalid_prev_frag (fragP, &prev_frag); 5730 5731 if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH) 5732 adjust = nds32_relax_branch_instructions (segment, fragP, 0, 1); 5733 if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL) 5734 prev_frag = NULL; 5735 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) 5736 adjust = 2; 5737 else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE) 5738 prev_frag = fragP; 5739 5740 return adjust; 5741 } 5742 5743 /* GAS will call this for each rs_machine_dependent fragment. The instruction 5744 is completed using the data from the relaxation pass. It may also create any 5745 necessary relocations. 5746 5747 *FRAGP has been relaxed to its final size, and now needs to have the bytes 5748 inside it modified to conform to the new size. It is called after relaxation 5749 is finished. 5750 5751 fragP->fr_type == rs_machine_dependent. 5752 fragP->fr_subtype is the subtype of what the address relaxed to. */ 5753 5754 void 5755 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP) 5756 { 5757 /* Convert branch relaxation instructions. */ 5758 symbolS *branch_symbol = fragP->fr_symbol; 5759 offsetT branch_offset = fragP->fr_offset; 5760 enum nds32_br_range branch_range_type = fragP->fr_subtype; 5761 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode; 5762 uint32_t origin_insn = fragP->tc_frag_data.insn; 5763 relax_info_t *relax_info; 5764 char *fr_buffer; 5765 int fr_where; 5766 int addend ATTRIBUTE_UNUSED; 5767 offsetT branch_target_address, branch_insn_address; 5768 expressionS exp; 5769 fixS *fixP; 5770 uint32_t *code_seq; 5771 uint32_t insn; 5772 int code_size, insn_size, offset, fixup_size; 5773 int buf_offset, pcrel; 5774 int i, k; 5775 uint16_t insn_16; 5776 nds32_relax_fixup_info_t fixup_info[MAX_RELAX_FIX]; 5777 /* Save the 1st instruction is converted to 16 bit or not. */ 5778 unsigned int branch_size; 5779 5780 /* Replace with gas_assert (branch_symbol != NULL); */ 5781 if (branch_symbol == NULL && !(fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)) 5782 return; 5783 5784 /* If frag_var is not enough room, the previos frag is fr_full and with 5785 opcode. The new one is rs_dependent but without opcode. */ 5786 if (opcode == NULL) 5787 return; 5788 5789 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE_BRANCH) 5790 { 5791 relax_info = hash_find (nds32_relax_info_hash, opcode->opcode); 5792 5793 if (relax_info == NULL) 5794 return; 5795 5796 i = BR_RANGE_S256; 5797 while (i < BR_RANGE_NUM 5798 && relax_info->relax_code_size[i] 5799 != (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED ? 4 : 2)) 5800 i++; 5801 5802 if (i >= BR_RANGE_NUM) 5803 as_bad ("Internal error: Cannot find relocation of" 5804 "relaxable branch."); 5805 5806 exp.X_op = O_symbol; 5807 exp.X_add_symbol = branch_symbol; 5808 exp.X_add_number = branch_offset; 5809 pcrel = ((relax_info->relax_fixup[i][0].ramp & NDS32_PCREL) != 0) ? 1 : 0; 5810 fr_where = fragP->fr_fix - 2; 5811 fixP = fix_new_exp (fragP, fr_where, relax_info->relax_fixup[i][0].size, 5812 &exp, pcrel, relax_info->relax_fixup[i][0].r_type); 5813 fixP->fx_addnumber = fixP->fx_offset; 5814 5815 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) 5816 { 5817 insn_16 = fragP->tc_frag_data.insn; 5818 nds32_convert_16_to_32 (stdoutput, insn_16, &insn); 5819 fr_buffer = fragP->fr_literal + fr_where; 5820 fragP->fr_fix += 2; 5821 exp.X_op = O_symbol; 5822 exp.X_add_symbol = abs_section_sym; 5823 exp.X_add_number = 0; 5824 fix_new_exp (fragP, fr_where, 4, 5825 &exp, 0, BFD_RELOC_NDS32_INSN16); 5826 number_to_chars_bigendian (fr_buffer, insn, 4); 5827 } 5828 } 5829 else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) 5830 { 5831 if (fragP->tc_frag_data.opcode->isize == 2) 5832 { 5833 insn_16 = fragP->tc_frag_data.insn; 5834 nds32_convert_16_to_32 (stdoutput, insn_16, &insn); 5835 } 5836 else 5837 insn = fragP->tc_frag_data.insn; 5838 fragP->fr_fix += 2; 5839 fr_where = fragP->fr_fix - 4; 5840 fr_buffer = fragP->fr_literal + fr_where; 5841 exp.X_op = O_symbol; 5842 exp.X_add_symbol = abs_section_sym; 5843 exp.X_add_number = 0; 5844 fix_new_exp (fragP, fr_where, 4, &exp, 0, 5845 BFD_RELOC_NDS32_INSN16); 5846 number_to_chars_bigendian (fr_buffer, insn, 4); 5847 } 5848 else if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH) 5849 { 5850 /* Branch instruction adjust and append relocations. */ 5851 relax_info = hash_find (nds32_relax_info_hash, opcode->opcode); 5852 5853 if (relax_info == NULL) 5854 return; 5855 5856 fr_where = fragP->fr_fix - opcode->isize; 5857 fr_buffer = fragP->fr_literal + fr_where; 5858 5859 if ((S_GET_SEGMENT (branch_symbol) != sec) 5860 || S_IS_WEAK (branch_symbol)) 5861 { 5862 if (fragP->fr_offset & 3) 5863 as_warn (_("Addend to unresolved symbol is not on word boundary.")); 5864 addend = 0; 5865 } 5866 else 5867 { 5868 /* Calculate symbol-to-instruction offset. */ 5869 branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset; 5870 branch_insn_address = fragP->fr_address + fr_where; 5871 addend = (branch_target_address - branch_insn_address) >> 1; 5872 } 5873 5874 code_size = relax_info->relax_code_size[branch_range_type]; 5875 code_seq = relax_info->relax_code_seq[branch_range_type]; 5876 5877 memcpy (fixup_info, relax_info->relax_fixup[branch_range_type], 5878 sizeof (fixup_info)); 5879 5880 /* Fill in frag. */ 5881 i = 0; 5882 k = 0; 5883 offset = 0; /* code_seq offset */ 5884 buf_offset = 0; /* fr_buffer offset */ 5885 while (offset < code_size) 5886 { 5887 insn = code_seq[i]; 5888 if (insn & 0x80000000) /* 16-bits instruction. */ 5889 { 5890 insn = (insn >> 16) & 0xFFFF; 5891 insn_size = 2; 5892 } 5893 else /* 32-bits instruction. */ 5894 { 5895 insn_size = 4; 5896 } 5897 5898 nds32_elf_get_set_cond (relax_info, offset, &insn, 5899 origin_insn, branch_range_type); 5900 5901 /* Try to convert to 16-bits instruction. Currently, only the first 5902 insntruction in pattern can be converted. EX: bnez sethi ori jr, 5903 only bnez can be converted to 16 bit and ori can't. */ 5904 5905 while (fixup_info[k].size != 0 5906 && relax_info->relax_fixup[branch_range_type][k].offset < offset) 5907 k++; 5908 5909 number_to_chars_bigendian (fr_buffer + buf_offset, insn, insn_size); 5910 buf_offset += insn_size; 5911 5912 offset += insn_size; 5913 i++; 5914 } 5915 5916 /* Set up fixup. */ 5917 exp.X_op = O_symbol; 5918 5919 for (i = 0; fixup_info[i].size != 0; i++) 5920 { 5921 fixup_size = fixup_info[i].size; 5922 pcrel = ((fixup_info[i].ramp & NDS32_PCREL) != 0) ? 1 : 0; 5923 5924 if ((fixup_info[i].ramp & NDS32_CREATE_LABEL) != 0) 5925 { 5926 /* This is a reverse branch. */ 5927 exp.X_add_symbol = symbol_temp_new (sec, 0, fragP->fr_next); 5928 exp.X_add_number = 0; 5929 } 5930 else if ((fixup_info[i].ramp & NDS32_PTR) != 0) 5931 { 5932 /* This relocation has to point to another instruction. */ 5933 branch_size = fr_where + code_size - 4; 5934 exp.X_add_symbol = symbol_temp_new (sec, branch_size, fragP); 5935 exp.X_add_number = 0; 5936 } 5937 else if ((fixup_info[i].ramp & NDS32_ABS) != 0) 5938 { 5939 /* This is a tag relocation. */ 5940 exp.X_add_symbol = abs_section_sym; 5941 exp.X_add_number = 0; 5942 } 5943 else if ((fixup_info[i].ramp & NDS32_INSN16) != 0) 5944 { 5945 if (!enable_16bit) 5946 continue; 5947 /* This is a tag relocation. */ 5948 exp.X_add_symbol = abs_section_sym; 5949 exp.X_add_number = 0; 5950 } 5951 else 5952 { 5953 exp.X_add_symbol = branch_symbol; 5954 exp.X_add_number = branch_offset; 5955 } 5956 5957 if (fixup_info[i].r_type != 0) 5958 { 5959 fixP = fix_new_exp (fragP, fr_where + fixup_info[i].offset, 5960 fixup_size, &exp, pcrel, 5961 fixup_info[i].r_type); 5962 fixP->fx_addnumber = fixP->fx_offset; 5963 } 5964 } 5965 5966 fragP->fr_fix = fr_where + buf_offset; 5967 } 5968 } 5969 5970 /* tc_frob_file_before_fix */ 5971 5972 void 5973 nds32_frob_file_before_fix (void) 5974 { 5975 } 5976 5977 static bfd_boolean 5978 nds32_relaxable_section (asection *sec) 5979 { 5980 return ((sec->flags & SEC_DEBUGGING) == 0 5981 && strcmp (sec->name, ".eh_frame") != 0); 5982 } 5983 5984 /* TC_FORCE_RELOCATION */ 5985 int 5986 nds32_force_relocation (fixS * fix) 5987 { 5988 switch (fix->fx_r_type) 5989 { 5990 case BFD_RELOC_NDS32_INSN16: 5991 case BFD_RELOC_NDS32_LABEL: 5992 case BFD_RELOC_NDS32_LONGCALL1: 5993 case BFD_RELOC_NDS32_LONGCALL2: 5994 case BFD_RELOC_NDS32_LONGCALL3: 5995 case BFD_RELOC_NDS32_LONGJUMP1: 5996 case BFD_RELOC_NDS32_LONGJUMP2: 5997 case BFD_RELOC_NDS32_LONGJUMP3: 5998 case BFD_RELOC_NDS32_LOADSTORE: 5999 case BFD_RELOC_NDS32_9_FIXED: 6000 case BFD_RELOC_NDS32_15_FIXED: 6001 case BFD_RELOC_NDS32_17_FIXED: 6002 case BFD_RELOC_NDS32_25_FIXED: 6003 case BFD_RELOC_NDS32_9_PCREL: 6004 case BFD_RELOC_NDS32_15_PCREL: 6005 case BFD_RELOC_NDS32_17_PCREL: 6006 case BFD_RELOC_NDS32_WORD_9_PCREL: 6007 case BFD_RELOC_NDS32_10_UPCREL: 6008 case BFD_RELOC_NDS32_25_PCREL: 6009 case BFD_RELOC_NDS32_MINUEND: 6010 case BFD_RELOC_NDS32_SUBTRAHEND: 6011 return 1; 6012 6013 case BFD_RELOC_8: 6014 case BFD_RELOC_16: 6015 case BFD_RELOC_32: 6016 case BFD_RELOC_NDS32_DIFF_ULEB128: 6017 /* Linker should handle difference between two symbol. */ 6018 return fix->fx_subsy != NULL 6019 && nds32_relaxable_section (S_GET_SEGMENT (fix->fx_addsy)); 6020 case BFD_RELOC_64: 6021 if (fix->fx_subsy) 6022 as_bad ("Double word for difference between two symbols " 6023 "is not supported across relaxation."); 6024 default: 6025 ; 6026 } 6027 6028 if (generic_force_reloc (fix)) 6029 return 1; 6030 6031 return fix->fx_pcrel; 6032 } 6033 6034 /* TC_VALIDATE_FIX_SUB */ 6035 6036 int 6037 nds32_validate_fix_sub (fixS *fix, segT add_symbol_segment) 6038 { 6039 segT sub_symbol_segment; 6040 6041 /* This code is referred from Xtensa. Check their implementation for 6042 details. */ 6043 6044 /* Make sure both symbols are in the same segment, and that segment is 6045 "normal" and relaxable. */ 6046 sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy); 6047 return (sub_symbol_segment == add_symbol_segment 6048 && add_symbol_segment != undefined_section); 6049 } 6050 6051 void 6052 md_number_to_chars (char *buf, valueT val, int n) 6053 { 6054 if (target_big_endian) 6055 number_to_chars_bigendian (buf, val, n); 6056 else 6057 number_to_chars_littleendian (buf, val, n); 6058 } 6059 6060 /* Equal to MAX_PRECISION in atof-ieee.c. */ 6061 #define MAX_LITTLENUMS 6 6062 6063 /* This function is called to convert an ASCII string into a floating point 6064 value in format used by the CPU. */ 6065 6066 char * 6067 md_atof (int type, char *litP, int *sizeP) 6068 { 6069 int i; 6070 int prec; 6071 LITTLENUM_TYPE words[MAX_LITTLENUMS]; 6072 char *t; 6073 6074 switch (type) 6075 { 6076 case 'f': 6077 case 'F': 6078 case 's': 6079 case 'S': 6080 prec = 2; 6081 break; 6082 case 'd': 6083 case 'D': 6084 case 'r': 6085 case 'R': 6086 prec = 4; 6087 break; 6088 default: 6089 *sizeP = 0; 6090 return _("Bad call to md_atof()"); 6091 } 6092 6093 t = atof_ieee (input_line_pointer, type, words); 6094 if (t) 6095 input_line_pointer = t; 6096 *sizeP = prec * sizeof (LITTLENUM_TYPE); 6097 6098 if (target_big_endian) 6099 { 6100 for (i = 0; i < prec; i++) 6101 { 6102 md_number_to_chars (litP, (valueT) words[i], 6103 sizeof (LITTLENUM_TYPE)); 6104 litP += sizeof (LITTLENUM_TYPE); 6105 } 6106 } 6107 else 6108 { 6109 for (i = prec - 1; i >= 0; i--) 6110 { 6111 md_number_to_chars (litP, (valueT) words[i], 6112 sizeof (LITTLENUM_TYPE)); 6113 litP += sizeof (LITTLENUM_TYPE); 6114 } 6115 } 6116 6117 return 0; 6118 } 6119 6120 /* md_elf_section_change_hook */ 6121 6122 void 6123 nds32_elf_section_change_hook (void) 6124 { 6125 } 6126 6127 /* md_cleanup */ 6128 6129 void 6130 nds32_cleanup (void) 6131 { 6132 } 6133 6134 /* This function is used to scan leb128 subtraction expressions, 6135 and insert fixups for them. 6136 6137 e.g., .leb128 .L1 - .L0 6138 6139 These expressions are heavily used in debug information or 6140 exception tables. Because relaxation will change code size, 6141 we must resolve them in link time. */ 6142 6143 static void 6144 nds32_insert_leb128_fixes (bfd *abfd ATTRIBUTE_UNUSED, 6145 asection *sec, void *xxx ATTRIBUTE_UNUSED) 6146 { 6147 segment_info_type *seginfo = seg_info (sec); 6148 struct frag *fragP; 6149 6150 subseg_set (sec, 0); 6151 6152 for (fragP = seginfo->frchainP->frch_root; 6153 fragP; fragP = fragP->fr_next) 6154 { 6155 expressionS *exp; 6156 6157 /* Only unsigned leb128 can be handle. */ 6158 if (fragP->fr_type != rs_leb128 || fragP->fr_subtype != 0 6159 || fragP->fr_symbol == NULL) 6160 continue; 6161 6162 exp = symbol_get_value_expression (fragP->fr_symbol); 6163 6164 if (exp->X_op != O_subtract) 6165 continue; 6166 6167 fix_new_exp (fragP, fragP->fr_fix, 0, 6168 exp, 0, BFD_RELOC_NDS32_DIFF_ULEB128); 6169 } 6170 } 6171 6172 static void 6173 nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, 6174 void *xxx ATTRIBUTE_UNUSED) 6175 { 6176 segment_info_type *seginfo; 6177 fragS *fragP; 6178 fixS *fixP; 6179 expressionS exp; 6180 fixS *fixp; 6181 6182 seginfo = seg_info (sec); 6183 if (!seginfo || !symbol_rootP || !subseg_text_p (sec) || sec->size == 0) 6184 return; 6185 /* If there is no relocation and relax is disabled, it is not necessary to 6186 insert R_NDS32_RELAX_ENTRY for linker do EX9 or IFC optimization. */ 6187 for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next) 6188 if (!fixp->fx_done) 6189 break; 6190 if (!fixp && !enable_relax_ex9 && !verbatim) 6191 return; 6192 6193 subseg_change (sec, 0); 6194 6195 /* Set RELAX_ENTRY flags for linker. */ 6196 fragP = seginfo->frchainP->frch_root; 6197 exp.X_op = O_symbol; 6198 exp.X_add_symbol = section_symbol (sec); 6199 exp.X_add_number = 0; 6200 if (!enable_relax_relocs) 6201 exp.X_add_number |= R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG; 6202 else 6203 { 6204 /* These flags are only enabled when global relax is enabled. 6205 Maybe we can check DISABLE_RELAX_FLAG at linke-time, 6206 so we set them anyway. */ 6207 if (enable_relax_ex9) 6208 exp.X_add_number |= R_NDS32_RELAX_ENTRY_EX9_FLAG; 6209 if (enable_relax_ifc) 6210 exp.X_add_number |= R_NDS32_RELAX_ENTRY_IFC_FLAG; 6211 if (verbatim) 6212 exp.X_add_number |= R_NDS32_RELAX_ENTRY_VERBATIM_FLAG; 6213 } 6214 if (optimize) 6215 exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG; 6216 if (optimize_for_space) 6217 exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FOR_SPACE_FLAG; 6218 6219 fixP = fix_new_exp (fragP, 0, 0, &exp, 0, BFD_RELOC_NDS32_RELAX_ENTRY); 6220 fixP->fx_no_overflow = 1; 6221 } 6222 6223 /* Analysis relax hint and insert suitable relocation pattern. */ 6224 6225 static void 6226 nds32_elf_analysis_relax_hint (void) 6227 { 6228 hash_traverse (nds32_hint_hash, nds32_elf_append_relax_relocs); 6229 } 6230 6231 static void 6232 nds32_elf_insert_final_frag (void) 6233 { 6234 struct frchain *frchainP; 6235 asection *s; 6236 fragS *fragP; 6237 6238 if (!optimize) 6239 return; 6240 6241 for (s = stdoutput->sections; s; s = s->next) 6242 { 6243 segment_info_type *seginfo = seg_info (s); 6244 if (!seginfo) 6245 continue; 6246 6247 for (frchainP = seginfo->frchainP; frchainP != NULL; 6248 frchainP = frchainP->frch_next) 6249 { 6250 subseg_set (s, frchainP->frch_subseg); 6251 6252 if (subseg_text_p (now_seg)) 6253 { 6254 fragP = frag_now; 6255 frag_var (rs_machine_dependent, 2, /* Max size. */ 6256 0, /* VAR is un-used. */ 0, NULL, 0, NULL); 6257 fragP->tc_frag_data.flag |= NDS32_FRAG_FINAL; 6258 } 6259 } 6260 } 6261 } 6262 6263 void 6264 md_end (void) 6265 { 6266 nds32_elf_insert_final_frag (); 6267 nds32_elf_analysis_relax_hint (); 6268 bfd_map_over_sections (stdoutput, nds32_insert_leb128_fixes, NULL); 6269 } 6270 6271 /* Implement md_allow_local_subtract. */ 6272 6273 bfd_boolean 6274 nds32_allow_local_subtract (expressionS *expr_l ATTRIBUTE_UNUSED, 6275 expressionS *expr_r ATTRIBUTE_UNUSED, 6276 segT sec ATTRIBUTE_UNUSED) 6277 { 6278 /* Don't allow any subtraction, because relax may change the code. */ 6279 return FALSE; 6280 } 6281 6282 /* Sort relocation by address. 6283 6284 We didn't use qsort () in stdlib, because quick-sort is not a stable 6285 sorting algorithm. Relocations at the same address (r_offset) must keep 6286 their relative order. For example, RELAX_ENTRY must be the very first 6287 relocation entry. 6288 6289 Currently, this function implements insertion-sort. */ 6290 6291 static int 6292 compar_relent (const void *lhs, const void *rhs) 6293 { 6294 const arelent **l = (const arelent **) lhs; 6295 const arelent **r = (const arelent **) rhs; 6296 6297 if ((*l)->address > (*r)->address) 6298 return 1; 6299 else if ((*l)->address == (*r)->address) 6300 return 0; 6301 else 6302 return -1; 6303 } 6304 6305 /* SET_SECTION_RELOCS () 6306 6307 Although this macro is originally used to set a relocation for each section, 6308 we use it to sort relocations in the same section by the address of the 6309 relocation. */ 6310 6311 void 6312 nds32_set_section_relocs (asection *sec, arelent ** relocs ATTRIBUTE_UNUSED, 6313 unsigned int n ATTRIBUTE_UNUSED) 6314 { 6315 bfd *abfd ATTRIBUTE_UNUSED = sec->owner; 6316 if (bfd_get_section_flags (abfd, sec) & (flagword) SEC_RELOC) 6317 nds32_insertion_sort (sec->orelocation, sec->reloc_count, 6318 sizeof (arelent**), compar_relent); 6319 } 6320 6321 long 6322 nds32_pcrel_from_section (fixS *fixP, segT sec ATTRIBUTE_UNUSED) 6323 { 6324 if (fixP->fx_addsy == NULL || !S_IS_DEFINED (fixP->fx_addsy) 6325 || S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)) 6326 { 6327 /* Let linker resolve undefined symbols. */ 6328 return 0; 6329 } 6330 6331 return fixP->fx_frag->fr_address + fixP->fx_where; 6332 } 6333 6334 /* md_post_relax_hook () 6335 Insert relax entry relocation into sections. */ 6336 6337 void 6338 nds32_post_relax_hook (void) 6339 { 6340 bfd_map_over_sections (stdoutput, nds32_insert_relax_entry, NULL); 6341 } 6342 6343 /* tc_fix_adjustable () 6344 6345 Return whether this symbol (fixup) can be replaced with 6346 section symbols. */ 6347 6348 bfd_boolean 6349 nds32_fix_adjustable (fixS *fixP) 6350 { 6351 switch (fixP->fx_r_type) 6352 { 6353 case BFD_RELOC_NDS32_WORD_9_PCREL: 6354 case BFD_RELOC_NDS32_9_PCREL: 6355 case BFD_RELOC_NDS32_15_PCREL: 6356 case BFD_RELOC_NDS32_17_PCREL: 6357 case BFD_RELOC_NDS32_25_PCREL: 6358 case BFD_RELOC_NDS32_HI20: 6359 case BFD_RELOC_NDS32_LO12S0: 6360 case BFD_RELOC_8: 6361 case BFD_RELOC_16: 6362 case BFD_RELOC_32: 6363 case BFD_RELOC_NDS32_PTR: 6364 case BFD_RELOC_NDS32_LONGCALL4: 6365 case BFD_RELOC_NDS32_LONGCALL5: 6366 case BFD_RELOC_NDS32_LONGCALL6: 6367 case BFD_RELOC_NDS32_LONGJUMP4: 6368 case BFD_RELOC_NDS32_LONGJUMP5: 6369 case BFD_RELOC_NDS32_LONGJUMP6: 6370 case BFD_RELOC_NDS32_LONGJUMP7: 6371 return 1; 6372 default: 6373 return 0; 6374 } 6375 } 6376 6377 /* elf_tc_final_processing */ 6378 6379 void 6380 elf_nds32_final_processing (void) 6381 { 6382 /* An FPU_COM instruction is found without previous non-FPU_COM 6383 instruction. */ 6384 if (nds32_fpu_com 6385 && !(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST))) 6386 { 6387 /* Since only FPU_COM instructions are used and no other FPU instructions 6388 are used. The nds32_elf_flags will be decided by the enabled options 6389 by command line or default configuration. */ 6390 if (nds32_fpu_dp_ext || nds32_fpu_sp_ext) 6391 { 6392 nds32_elf_flags |= nds32_fpu_dp_ext ? E_NDS32_HAS_FPU_DP_INST : 0; 6393 nds32_elf_flags |= nds32_fpu_sp_ext ? E_NDS32_HAS_FPU_INST : 0; 6394 } 6395 else 6396 { 6397 /* Should never here. */ 6398 as_bad (_("Used FPU instructions requires enabling FPU extension")); 6399 } 6400 } 6401 6402 if (nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)) 6403 { 6404 /* Single/double FPU has been used, set FPU register config. */ 6405 /* We did not check the actual number of register used. We may 6406 want to do it while assemble. */ 6407 nds32_elf_flags &= ~E_NDS32_FPU_REG_CONF; 6408 nds32_elf_flags |= (nds32_freg << E_NDS32_FPU_REG_CONF_SHIFT); 6409 } 6410 6411 if (nds32_pic) 6412 nds32_elf_flags |= E_NDS32_HAS_PIC; 6413 6414 if (nds32_gpr16) 6415 nds32_elf_flags |= E_NDS32_HAS_REDUCED_REGS; 6416 6417 nds32_elf_flags |= (E_NDS32_ELF_VER_1_4 | nds32_abi); 6418 elf_elfheader (stdoutput)->e_flags |= nds32_elf_flags; 6419 } 6420 6421 /* Implement md_apply_fix. Apply the fix-up or tranform the fix-up for 6422 later relocation generation. */ 6423 6424 void 6425 nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) 6426 { 6427 char *where = fixP->fx_frag->fr_literal + fixP->fx_where; 6428 bfd_vma value = *valP; 6429 6430 if (fixP->fx_r_type < BFD_RELOC_UNUSED 6431 && fixP->fx_r_type > BFD_RELOC_NONE 6432 && fixP->fx_r_type != BFD_RELOC_NDS32_DIFF_ULEB128) 6433 { 6434 /* In our old nds32 binutils, it must convert relocations which is 6435 generated by CGEN. However, it does not have to consider this anymore. 6436 In current, it only deal with data relocations which enum 6437 is smaller than BFD_RELOC_NONE and BFD_RELOC_NDS32_DIFF_ULEB128. 6438 It is believed that we can construct a better mechanism to 6439 deal with the whole relocation issue in nds32 target 6440 without using CGEN. */ 6441 fixP->fx_addnumber = value; 6442 fixP->tc_fix_data = NULL; 6443 6444 /* Tranform specific relocations here for later relocation generation. 6445 Tag data here for ex9 relaxtion and tag tls data for linker. */ 6446 switch (fixP->fx_r_type) 6447 { 6448 case BFD_RELOC_NDS32_DATA: 6449 if (!enable_relax_ex9) 6450 fixP->fx_done = 1; 6451 break; 6452 case BFD_RELOC_NDS32_TPOFF: 6453 case BFD_RELOC_NDS32_TLS_LE_HI20: 6454 case BFD_RELOC_NDS32_TLS_LE_LO12: 6455 case BFD_RELOC_NDS32_TLS_LE_ADD: 6456 case BFD_RELOC_NDS32_TLS_LE_LS: 6457 case BFD_RELOC_NDS32_GOTTPOFF: 6458 case BFD_RELOC_NDS32_TLS_IE_HI20: 6459 case BFD_RELOC_NDS32_TLS_IE_LO12S2: 6460 S_SET_THREAD_LOCAL (fixP->fx_addsy); 6461 break; 6462 default: 6463 break; 6464 } 6465 return; 6466 } 6467 6468 if (fixP->fx_addsy == (symbolS *) NULL) 6469 fixP->fx_done = 1; 6470 6471 if (fixP->fx_subsy != (symbolS *) NULL) 6472 { 6473 /* HOW DIFF RELOCATION WORKS. 6474 6475 First of all, this relocation is used to calculate the distance 6476 between two symbols in the SAME section. It is used for jump- 6477 table, debug information, exception table, et al. Therefore, 6478 it is a unsigned positive value. It is NOT used for general- 6479 purpose arithmetic. 6480 6481 Consider this example, the distance between .LEND and .LBEGIN 6482 is stored at the address of foo. 6483 6484 ---- >8 ---- >8 ---- >8 ---- >8 ---- 6485 .data 6486 foo: 6487 .word .LBEGIN - .LEND 6488 6489 .text 6490 [before] 6491 .LBEGIN 6492 \ 6493 [between] distance 6494 / 6495 .LEND 6496 [after] 6497 ---- 8< ---- 8< ---- 8< ---- 8< ---- 6498 6499 We use a single relocation entry for this expression. 6500 * The initial distance value is stored direcly in that location 6501 specified by r_offset (i.e., foo in this example.) 6502 * The begin of the region, i.e., .LBEGIN, is specified by 6503 r_info/R_SYM and r_addend, e.g., .text + 0x32. 6504 * The end of region, i.e., .LEND, is represented by 6505 .LBEGIN + distance instead of .LEND, so we only need 6506 a single relocation entry instead of two. 6507 6508 When an instruction is relaxed, we adjust the relocation entry 6509 depending on where the instruction locates. There are three 6510 cases, before, after and between the region. 6511 * between: Distance value is read from r_offset, adjusted and 6512 written back into r_offset. 6513 * before: Only r_addend is adjust. 6514 * after: We don't care about it. 6515 6516 Hereby, there are some limitation. 6517 6518 `(.LEND - 1) - .LBEGIN' and `(.LEND - .LBEGIN) - 1' 6519 are semantically different, and we cannot handle latter case 6520 when relaxation. 6521 6522 The latter expression means subtracting 1 from the distance 6523 between .LEND and .LBEGIN. And the former expression means 6524 the distance between (.LEND - 1) and .LBEGIN. 6525 6526 The nuance affects whether to adjust distance value when relax 6527 an instruction. In another words, whether the instruction 6528 locates in the region. Because we use a single relocation entry, 6529 there is no field left for .LEND and the subtrahend. 6530 6531 Since GCC-4.5, GCC may produce debug information in such expression 6532 .long .L1-1-.L0 6533 in order to describe register clobbering during an function-call. 6534 .L0: 6535 call foo 6536 .L1: 6537 6538 Check http://gcc.gnu.org/ml/gcc-patches/2009-06/msg01317.html 6539 for details. */ 6540 6541 value -= S_GET_VALUE (fixP->fx_subsy); 6542 *valP = value; 6543 fixP->fx_subsy = NULL; 6544 fixP->fx_offset -= value; 6545 6546 switch (fixP->fx_r_type) 6547 { 6548 case BFD_RELOC_8: 6549 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF8; 6550 md_number_to_chars (where, value, 1); 6551 break; 6552 case BFD_RELOC_16: 6553 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF16; 6554 md_number_to_chars (where, value, 2); 6555 break; 6556 case BFD_RELOC_32: 6557 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF32; 6558 md_number_to_chars (where, value, 4); 6559 break; 6560 case BFD_RELOC_NDS32_DIFF_ULEB128: 6561 /* cvt_frag_to_fill () has called output_leb128 () for us. */ 6562 break; 6563 default: 6564 as_bad_where (fixP->fx_file, fixP->fx_line, 6565 _("expression too complex")); 6566 return; 6567 } 6568 } 6569 else if (fixP->fx_done) 6570 { 6571 /* We're finished with this fixup. Install it because 6572 bfd_install_relocation won't be called to do it. */ 6573 switch (fixP->fx_r_type) 6574 { 6575 case BFD_RELOC_8: 6576 md_number_to_chars (where, value, 1); 6577 break; 6578 case BFD_RELOC_16: 6579 md_number_to_chars (where, value, 2); 6580 break; 6581 case BFD_RELOC_32: 6582 md_number_to_chars (where, value, 4); 6583 break; 6584 case BFD_RELOC_64: 6585 md_number_to_chars (where, value, 8); 6586 default: 6587 as_bad_where (fixP->fx_file, fixP->fx_line, 6588 _("Internal error: Unknown fixup type %d (`%s')"), 6589 fixP->fx_r_type, 6590 bfd_get_reloc_code_name (fixP->fx_r_type)); 6591 break; 6592 } 6593 } 6594 } 6595 6596 /* Implement tc_gen_reloc. Generate ELF relocation for a fix-up. */ 6597 6598 arelent * 6599 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP) 6600 { 6601 arelent *reloc; 6602 bfd_reloc_code_real_type code; 6603 6604 reloc = (arelent *) xmalloc (sizeof (arelent)); 6605 6606 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); 6607 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy); 6608 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where; 6609 6610 code = fixP->fx_r_type; 6611 6612 reloc->howto = bfd_reloc_type_lookup (stdoutput, code); 6613 if (reloc->howto == (reloc_howto_type *) NULL) 6614 { 6615 as_bad_where (fixP->fx_file, fixP->fx_line, 6616 _("internal error: can't export reloc type %d (`%s')"), 6617 fixP->fx_r_type, bfd_get_reloc_code_name (code)); 6618 return NULL; 6619 } 6620 6621 /* Add relocation handling here. */ 6622 6623 switch (fixP->fx_r_type) 6624 { 6625 default: 6626 /* In general, addend of a relocation is the offset to the 6627 associated symbol. */ 6628 reloc->addend = fixP->fx_offset; 6629 break; 6630 6631 case BFD_RELOC_NDS32_DATA: 6632 /* Prevent linker from optimizing data in text sections. 6633 For example, jump table. */ 6634 reloc->addend = fixP->fx_size; 6635 break; 6636 } 6637 6638 return reloc; 6639 } 6640 6641 struct suffix_name suffix_table[] = 6642 { 6643 {"GOTOFF", BFD_RELOC_NDS32_GOTOFF, 1}, 6644 {"GOT", BFD_RELOC_NDS32_GOT20, 1}, 6645 {"TPOFF", BFD_RELOC_NDS32_TPOFF, 0}, 6646 {"PLT", BFD_RELOC_NDS32_25_PLTREL, 1}, 6647 {"GOTTPOFF", BFD_RELOC_NDS32_GOTTPOFF, 0} 6648 }; 6649 6650 /* Implement md_parse_name. */ 6651 6652 int 6653 nds32_parse_name (char const *name, expressionS *exprP, 6654 enum expr_mode mode ATTRIBUTE_UNUSED, 6655 char *nextcharP ATTRIBUTE_UNUSED) 6656 { 6657 segT segment; 6658 6659 exprP->X_op_symbol = NULL; 6660 exprP->X_md = BFD_RELOC_UNUSED; 6661 6662 exprP->X_add_symbol = symbol_find_or_make (name); 6663 exprP->X_op = O_symbol; 6664 exprP->X_add_number = 0; 6665 6666 /* Check the specail name if a symbol. */ 6667 segment = S_GET_SEGMENT (exprP->X_add_symbol); 6668 if (segment != undefined_section) 6669 return 0; 6670 6671 if (strcmp (name, GOT_NAME) == 0 && *nextcharP != '@') 6672 { 6673 /* Set for _GOT_OFFSET_TABLE_. */ 6674 exprP->X_md = BFD_RELOC_NDS32_GOTPC20; 6675 } 6676 else if (*nextcharP == '@') 6677 { 6678 size_t i; 6679 char *next; 6680 for (i = 0; i < ARRAY_SIZE (suffix_table); i++) 6681 { 6682 next = input_line_pointer + 1 + strlen(suffix_table[i].suffix); 6683 if (strncasecmp (input_line_pointer + 1, suffix_table[i].suffix, 6684 strlen (suffix_table[i].suffix)) == 0 6685 && !is_part_of_name (*next)) 6686 { 6687 if (!nds32_pic && suffix_table[i].pic) 6688 as_bad (_("need PIC qualifier with symbol.")); 6689 exprP->X_md = suffix_table[i].reloc; 6690 *input_line_pointer = *nextcharP; 6691 input_line_pointer = next; 6692 *nextcharP = *input_line_pointer; 6693 *input_line_pointer = '\0'; 6694 break; 6695 } 6696 } 6697 } 6698 return 1; 6699 } 6700 6701 /* Implement tc_regname_to_dw2regnum. */ 6702 6703 int 6704 tc_nds32_regname_to_dw2regnum (char *regname) 6705 { 6706 struct nds32_keyword *sym = hash_find (nds32_gprs_hash, regname); 6707 6708 if (!sym) 6709 return -1; 6710 6711 return sym->value; 6712 } 6713 6714 void 6715 tc_nds32_frame_initial_instructions (void) 6716 { 6717 /* CIE */ 6718 /* Default cfa is register-31/sp. */ 6719 cfi_add_CFA_def_cfa (31, 0); 6720 } 6721