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