1 1.1 christos /* tc-moxie.c -- Assemble code for moxie 2 1.10 christos Copyright (C) 2009-2025 Free Software Foundation, Inc. 3 1.1 christos 4 1.1 christos This file is part of GAS, the GNU Assembler. 5 1.1 christos 6 1.1 christos GAS is free software; you can redistribute it and/or modify 7 1.1 christos it under the terms of the GNU General Public License as published by 8 1.1 christos the Free Software Foundation; either version 3, or (at your option) 9 1.1 christos any later version. 10 1.1 christos 11 1.1 christos GAS is distributed in the hope that it will be useful, 12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 1.1 christos GNU General Public License for more details. 15 1.1 christos 16 1.1 christos You should have received a copy of the GNU General Public License 17 1.1 christos along with GAS; see the file COPYING. If not, write to 18 1.1 christos the Free Software Foundation, 51 Franklin Street - Fifth Floor, 19 1.1 christos Boston, MA 02110-1301, USA. */ 20 1.1 christos 21 1.1 christos /* Contributed by Anthony Green <green (at) moxielogic.com>. */ 22 1.1 christos 23 1.1 christos #include "as.h" 24 1.1 christos #include "safe-ctype.h" 25 1.1 christos #include "opcode/moxie.h" 26 1.1 christos #include "elf/moxie.h" 27 1.1 christos 28 1.1 christos extern const moxie_opc_info_t moxie_opc_info[128]; 29 1.1 christos 30 1.1 christos const char comment_chars[] = "#"; 31 1.1 christos const char line_separator_chars[] = ";"; 32 1.1 christos const char line_comment_chars[] = "#"; 33 1.1 christos 34 1.1 christos static int pending_reloc; 35 1.8 christos static htab_t opcode_hash_control; 36 1.1 christos 37 1.1 christos const pseudo_typeS md_pseudo_table[] = 38 1.1 christos { 39 1.1 christos {0, 0, 0} 40 1.1 christos }; 41 1.1 christos 42 1.1 christos const char FLT_CHARS[] = "rRsSfFdDxXpP"; 43 1.1 christos const char EXP_CHARS[] = "eE"; 44 1.1 christos 45 1.3 christos static valueT md_chars_to_number (char * buf, int n); 46 1.3 christos 47 1.3 christos /* Byte order. */ 48 1.3 christos extern int target_big_endian; 49 1.1 christos 50 1.1 christos void 51 1.1 christos md_operand (expressionS *op __attribute__((unused))) 52 1.1 christos { 53 1.1 christos /* Empty for now. */ 54 1.1 christos } 55 1.1 christos 56 1.1 christos /* This function is called once, at assembler startup time. It sets 57 1.1 christos up the hash table with all the opcodes in it, and also initializes 58 1.1 christos some aliases for compatibility with other assemblers. */ 59 1.1 christos 60 1.1 christos void 61 1.1 christos md_begin (void) 62 1.1 christos { 63 1.1 christos int count; 64 1.1 christos const moxie_opc_info_t *opcode; 65 1.8 christos opcode_hash_control = str_htab_create (); 66 1.1 christos 67 1.1 christos /* Insert names into hash table. */ 68 1.1 christos for (count = 0, opcode = moxie_form1_opc_info; count++ < 64; opcode++) 69 1.8 christos str_hash_insert (opcode_hash_control, opcode->name, opcode, 0); 70 1.1 christos 71 1.1 christos for (count = 0, opcode = moxie_form2_opc_info; count++ < 4; opcode++) 72 1.8 christos str_hash_insert (opcode_hash_control, opcode->name, opcode, 0); 73 1.1 christos 74 1.1 christos for (count = 0, opcode = moxie_form3_opc_info; count++ < 10; opcode++) 75 1.8 christos str_hash_insert (opcode_hash_control, opcode->name, opcode, 0); 76 1.3 christos 77 1.1 christos bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0); 78 1.1 christos } 79 1.1 christos 80 1.1 christos /* Parse an expression and then restore the input line pointer. */ 81 1.1 christos 82 1.1 christos static char * 83 1.1 christos parse_exp_save_ilp (char *s, expressionS *op) 84 1.1 christos { 85 1.1 christos char *save = input_line_pointer; 86 1.1 christos 87 1.1 christos input_line_pointer = s; 88 1.1 christos expression (op); 89 1.1 christos s = input_line_pointer; 90 1.1 christos input_line_pointer = save; 91 1.1 christos return s; 92 1.1 christos } 93 1.1 christos 94 1.1 christos static int 95 1.1 christos parse_register_operand (char **ptr) 96 1.1 christos { 97 1.1 christos int reg; 98 1.1 christos char *s = *ptr; 99 1.1 christos 100 1.1 christos if (*s != '$') 101 1.1 christos { 102 1.1 christos as_bad (_("expecting register")); 103 1.1 christos ignore_rest_of_line (); 104 1.1 christos return -1; 105 1.1 christos } 106 1.1 christos if (s[1] == 'f' && s[2] == 'p') 107 1.1 christos { 108 1.1 christos *ptr += 3; 109 1.1 christos return 0; 110 1.1 christos } 111 1.1 christos if (s[1] == 's' && s[2] == 'p') 112 1.1 christos { 113 1.1 christos *ptr += 3; 114 1.1 christos return 1; 115 1.1 christos } 116 1.1 christos if (s[1] == 'r') 117 1.1 christos { 118 1.1 christos reg = s[2] - '0'; 119 1.1 christos if ((reg < 0) || (reg > 9)) 120 1.1 christos { 121 1.1 christos as_bad (_("illegal register number")); 122 1.1 christos ignore_rest_of_line (); 123 1.1 christos return -1; 124 1.1 christos } 125 1.1 christos if (reg == 1) 126 1.1 christos { 127 1.1 christos int r2 = s[3] - '0'; 128 1.1 christos if ((r2 >= 0) && (r2 <= 3)) 129 1.1 christos { 130 1.1 christos reg = 10 + r2; 131 1.1 christos *ptr += 1; 132 1.1 christos } 133 1.1 christos } 134 1.1 christos } 135 1.1 christos else 136 1.1 christos { 137 1.1 christos as_bad (_("illegal register number")); 138 1.1 christos ignore_rest_of_line (); 139 1.1 christos return -1; 140 1.1 christos } 141 1.1 christos 142 1.1 christos *ptr += 3; 143 1.1 christos 144 1.1 christos return reg + 2; 145 1.1 christos } 146 1.1 christos 147 1.1 christos /* This is the guts of the machine-dependent assembler. STR points to 148 1.1 christos a machine dependent instruction. This function is supposed to emit 149 1.1 christos the frags/bytes it assembles to. */ 150 1.1 christos 151 1.1 christos void 152 1.1 christos md_assemble (char *str) 153 1.1 christos { 154 1.1 christos char *op_start; 155 1.1 christos char *op_end; 156 1.1 christos 157 1.1 christos moxie_opc_info_t *opcode; 158 1.1 christos char *p; 159 1.1 christos char pend; 160 1.1 christos 161 1.1 christos unsigned short iword = 0; 162 1.1 christos 163 1.1 christos int nlen = 0; 164 1.1 christos 165 1.1 christos /* Drop leading whitespace. */ 166 1.10 christos while (is_whitespace (*str)) 167 1.1 christos str++; 168 1.1 christos 169 1.1 christos /* Find the op code end. */ 170 1.1 christos op_start = str; 171 1.1 christos for (op_end = str; 172 1.10 christos !is_end_of_stmt (*op_end) && !is_whitespace (*op_end); 173 1.1 christos op_end++) 174 1.1 christos nlen++; 175 1.1 christos 176 1.1 christos pend = *op_end; 177 1.1 christos *op_end = 0; 178 1.1 christos 179 1.1 christos if (nlen == 0) 180 1.1 christos as_bad (_("can't find opcode ")); 181 1.10 christos opcode = str_hash_find (opcode_hash_control, op_start); 182 1.1 christos *op_end = pend; 183 1.1 christos 184 1.1 christos if (opcode == NULL) 185 1.1 christos { 186 1.1 christos as_bad (_("unknown opcode %s"), op_start); 187 1.1 christos return; 188 1.1 christos } 189 1.1 christos 190 1.1 christos p = frag_more (2); 191 1.1 christos 192 1.1 christos switch (opcode->itype) 193 1.1 christos { 194 1.1 christos case MOXIE_F2_A8V: 195 1.1 christos iword = (1<<15) | (opcode->opcode << 12); 196 1.10 christos while (is_whitespace (*op_end)) 197 1.1 christos op_end++; 198 1.1 christos { 199 1.1 christos expressionS arg; 200 1.1 christos int reg; 201 1.1 christos reg = parse_register_operand (&op_end); 202 1.1 christos iword += (reg << 8); 203 1.1 christos if (*op_end != ',') 204 1.1 christos as_warn (_("expecting comma delimited register operands")); 205 1.1 christos op_end++; 206 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg); 207 1.1 christos fix_new_exp (frag_now, 208 1.3 christos ((p + (target_big_endian ? 1 : 0)) - frag_now->fr_literal), 209 1.1 christos 1, 210 1.1 christos &arg, 211 1.1 christos 0, 212 1.1 christos BFD_RELOC_8); 213 1.1 christos } 214 1.1 christos break; 215 1.1 christos case MOXIE_F1_AB: 216 1.1 christos iword = opcode->opcode << 8; 217 1.10 christos while (is_whitespace (*op_end)) 218 1.1 christos op_end++; 219 1.1 christos { 220 1.1 christos int dest, src; 221 1.1 christos dest = parse_register_operand (&op_end); 222 1.1 christos if (*op_end != ',') 223 1.1 christos as_warn (_("expecting comma delimited register operands")); 224 1.1 christos op_end++; 225 1.1 christos src = parse_register_operand (&op_end); 226 1.1 christos iword += (dest << 4) + src; 227 1.10 christos while (is_whitespace (*op_end)) 228 1.1 christos op_end++; 229 1.1 christos if (*op_end != 0) 230 1.1 christos as_warn (_("extra stuff on line ignored")); 231 1.1 christos } 232 1.1 christos break; 233 1.1 christos case MOXIE_F1_A4: 234 1.1 christos iword = opcode->opcode << 8; 235 1.10 christos while (is_whitespace (*op_end)) 236 1.1 christos op_end++; 237 1.1 christos { 238 1.1 christos expressionS arg; 239 1.1 christos char *where; 240 1.1 christos int regnum; 241 1.1 christos 242 1.1 christos regnum = parse_register_operand (&op_end); 243 1.10 christos while (is_whitespace (*op_end)) 244 1.1 christos op_end++; 245 1.1 christos 246 1.1 christos iword += (regnum << 4); 247 1.1 christos 248 1.1 christos if (*op_end != ',') 249 1.1 christos { 250 1.1 christos as_bad (_("expecting comma delimited operands")); 251 1.1 christos ignore_rest_of_line (); 252 1.1 christos return; 253 1.1 christos } 254 1.1 christos op_end++; 255 1.1 christos 256 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg); 257 1.1 christos where = frag_more (4); 258 1.1 christos fix_new_exp (frag_now, 259 1.1 christos (where - frag_now->fr_literal), 260 1.1 christos 4, 261 1.1 christos &arg, 262 1.1 christos 0, 263 1.1 christos BFD_RELOC_32); 264 1.1 christos } 265 1.1 christos break; 266 1.1 christos case MOXIE_F1_M: 267 1.1 christos case MOXIE_F1_4: 268 1.1 christos iword = opcode->opcode << 8; 269 1.10 christos while (is_whitespace (*op_end)) 270 1.1 christos op_end++; 271 1.1 christos { 272 1.1 christos expressionS arg; 273 1.1 christos char *where; 274 1.1 christos 275 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg); 276 1.1 christos where = frag_more (4); 277 1.1 christos fix_new_exp (frag_now, 278 1.1 christos (where - frag_now->fr_literal), 279 1.1 christos 4, 280 1.1 christos &arg, 281 1.1 christos 0, 282 1.1 christos BFD_RELOC_32); 283 1.1 christos } 284 1.1 christos break; 285 1.1 christos case MOXIE_F1_NARG: 286 1.1 christos iword = opcode->opcode << 8; 287 1.10 christos while (is_whitespace (*op_end)) 288 1.1 christos op_end++; 289 1.1 christos if (*op_end != 0) 290 1.1 christos as_warn (_("extra stuff on line ignored")); 291 1.1 christos break; 292 1.1 christos case MOXIE_F1_A: 293 1.1 christos iword = opcode->opcode << 8; 294 1.10 christos while (is_whitespace (*op_end)) 295 1.1 christos op_end++; 296 1.1 christos { 297 1.1 christos int reg; 298 1.1 christos reg = parse_register_operand (&op_end); 299 1.10 christos while (is_whitespace (*op_end)) 300 1.1 christos op_end++; 301 1.1 christos if (*op_end != 0) 302 1.1 christos as_warn (_("extra stuff on line ignored")); 303 1.1 christos iword += (reg << 4); 304 1.1 christos } 305 1.1 christos break; 306 1.1 christos case MOXIE_F1_ABi: 307 1.1 christos iword = opcode->opcode << 8; 308 1.10 christos while (is_whitespace (*op_end)) 309 1.1 christos op_end++; 310 1.1 christos { 311 1.1 christos int a, b; 312 1.1 christos a = parse_register_operand (&op_end); 313 1.1 christos if (*op_end != ',') 314 1.1 christos as_warn (_("expecting comma delimited register operands")); 315 1.1 christos op_end++; 316 1.1 christos if (*op_end != '(') 317 1.1 christos { 318 1.1 christos as_bad (_("expecting indirect register `($rA)'")); 319 1.1 christos ignore_rest_of_line (); 320 1.1 christos return; 321 1.1 christos } 322 1.1 christos op_end++; 323 1.1 christos b = parse_register_operand (&op_end); 324 1.1 christos if (*op_end != ')') 325 1.1 christos { 326 1.1 christos as_bad (_("missing closing parenthesis")); 327 1.1 christos ignore_rest_of_line (); 328 1.1 christos return; 329 1.1 christos } 330 1.1 christos op_end++; 331 1.1 christos iword += (a << 4) + b; 332 1.10 christos while (is_whitespace (*op_end)) 333 1.1 christos op_end++; 334 1.1 christos if (*op_end != 0) 335 1.1 christos as_warn (_("extra stuff on line ignored")); 336 1.1 christos } 337 1.1 christos break; 338 1.1 christos case MOXIE_F1_AiB: 339 1.1 christos iword = opcode->opcode << 8; 340 1.10 christos while (is_whitespace (*op_end)) 341 1.1 christos op_end++; 342 1.1 christos { 343 1.1 christos int a, b; 344 1.1 christos if (*op_end != '(') 345 1.1 christos { 346 1.1 christos as_bad (_("expecting indirect register `($rA)'")); 347 1.1 christos ignore_rest_of_line (); 348 1.1 christos return; 349 1.1 christos } 350 1.1 christos op_end++; 351 1.1 christos a = parse_register_operand (&op_end); 352 1.1 christos if (*op_end != ')') 353 1.1 christos { 354 1.1 christos as_bad (_("missing closing parenthesis")); 355 1.1 christos ignore_rest_of_line (); 356 1.1 christos return; 357 1.1 christos } 358 1.1 christos op_end++; 359 1.1 christos if (*op_end != ',') 360 1.1 christos as_warn (_("expecting comma delimited register operands")); 361 1.1 christos op_end++; 362 1.1 christos b = parse_register_operand (&op_end); 363 1.1 christos iword += (a << 4) + b; 364 1.10 christos while (is_whitespace (*op_end)) 365 1.1 christos op_end++; 366 1.1 christos if (*op_end != 0) 367 1.1 christos as_warn (_("extra stuff on line ignored")); 368 1.1 christos } 369 1.1 christos break; 370 1.1 christos case MOXIE_F1_4A: 371 1.1 christos iword = opcode->opcode << 8; 372 1.10 christos while (is_whitespace (*op_end)) 373 1.1 christos op_end++; 374 1.1 christos { 375 1.1 christos expressionS arg; 376 1.1 christos char *where; 377 1.1 christos int a; 378 1.1 christos 379 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg); 380 1.1 christos where = frag_more (4); 381 1.1 christos fix_new_exp (frag_now, 382 1.1 christos (where - frag_now->fr_literal), 383 1.1 christos 4, 384 1.1 christos &arg, 385 1.1 christos 0, 386 1.1 christos BFD_RELOC_32); 387 1.1 christos 388 1.1 christos if (*op_end != ',') 389 1.1 christos { 390 1.1 christos as_bad (_("expecting comma delimited operands")); 391 1.1 christos ignore_rest_of_line (); 392 1.1 christos return; 393 1.1 christos } 394 1.1 christos op_end++; 395 1.1 christos 396 1.1 christos a = parse_register_operand (&op_end); 397 1.10 christos while (is_whitespace (*op_end)) 398 1.1 christos op_end++; 399 1.1 christos if (*op_end != 0) 400 1.1 christos as_warn (_("extra stuff on line ignored")); 401 1.1 christos 402 1.1 christos iword += (a << 4); 403 1.1 christos } 404 1.1 christos break; 405 1.3 christos case MOXIE_F1_ABi2: 406 1.1 christos iword = opcode->opcode << 8; 407 1.10 christos while (is_whitespace (*op_end)) 408 1.1 christos op_end++; 409 1.1 christos { 410 1.1 christos expressionS arg; 411 1.1 christos char *offset; 412 1.1 christos int a, b; 413 1.1 christos 414 1.1 christos a = parse_register_operand (&op_end); 415 1.10 christos while (is_whitespace (*op_end)) 416 1.1 christos op_end++; 417 1.1 christos 418 1.1 christos if (*op_end != ',') 419 1.1 christos { 420 1.1 christos as_bad (_("expecting comma delimited operands")); 421 1.1 christos ignore_rest_of_line (); 422 1.1 christos return; 423 1.1 christos } 424 1.1 christos op_end++; 425 1.1 christos 426 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg); 427 1.3 christos offset = frag_more (2); 428 1.1 christos fix_new_exp (frag_now, 429 1.1 christos (offset - frag_now->fr_literal), 430 1.3 christos 2, 431 1.1 christos &arg, 432 1.1 christos 0, 433 1.3 christos BFD_RELOC_16); 434 1.1 christos 435 1.1 christos if (*op_end != '(') 436 1.1 christos { 437 1.1 christos as_bad (_("expecting indirect register `($rX)'")); 438 1.1 christos ignore_rest_of_line (); 439 1.1 christos return; 440 1.1 christos } 441 1.1 christos op_end++; 442 1.1 christos b = parse_register_operand (&op_end); 443 1.1 christos if (*op_end != ')') 444 1.1 christos { 445 1.1 christos as_bad (_("missing closing parenthesis")); 446 1.1 christos ignore_rest_of_line (); 447 1.1 christos return; 448 1.1 christos } 449 1.1 christos op_end++; 450 1.1 christos 451 1.10 christos while (is_whitespace (*op_end)) 452 1.1 christos op_end++; 453 1.1 christos if (*op_end != 0) 454 1.1 christos as_warn (_("extra stuff on line ignored")); 455 1.1 christos 456 1.1 christos iword += (a << 4) + b; 457 1.1 christos } 458 1.1 christos break; 459 1.3 christos case MOXIE_F1_AiB2: 460 1.1 christos iword = opcode->opcode << 8; 461 1.10 christos while (is_whitespace (*op_end)) 462 1.1 christos op_end++; 463 1.1 christos { 464 1.1 christos expressionS arg; 465 1.1 christos char *offset; 466 1.1 christos int a, b; 467 1.1 christos 468 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg); 469 1.3 christos offset = frag_more (2); 470 1.1 christos fix_new_exp (frag_now, 471 1.1 christos (offset - frag_now->fr_literal), 472 1.3 christos 2, 473 1.1 christos &arg, 474 1.1 christos 0, 475 1.3 christos BFD_RELOC_16); 476 1.1 christos 477 1.1 christos if (*op_end != '(') 478 1.1 christos { 479 1.1 christos as_bad (_("expecting indirect register `($rX)'")); 480 1.1 christos ignore_rest_of_line (); 481 1.1 christos return; 482 1.1 christos } 483 1.1 christos op_end++; 484 1.1 christos a = parse_register_operand (&op_end); 485 1.1 christos if (*op_end != ')') 486 1.1 christos { 487 1.1 christos as_bad (_("missing closing parenthesis")); 488 1.1 christos ignore_rest_of_line (); 489 1.1 christos return; 490 1.1 christos } 491 1.1 christos op_end++; 492 1.1 christos 493 1.1 christos if (*op_end != ',') 494 1.1 christos { 495 1.1 christos as_bad (_("expecting comma delimited operands")); 496 1.1 christos ignore_rest_of_line (); 497 1.1 christos return; 498 1.1 christos } 499 1.1 christos op_end++; 500 1.1 christos 501 1.1 christos b = parse_register_operand (&op_end); 502 1.10 christos while (is_whitespace (*op_end)) 503 1.1 christos op_end++; 504 1.1 christos if (*op_end != 0) 505 1.1 christos as_warn (_("extra stuff on line ignored")); 506 1.1 christos 507 1.1 christos iword += (a << 4) + b; 508 1.1 christos } 509 1.1 christos break; 510 1.1 christos case MOXIE_F2_NARG: 511 1.1 christos iword = opcode->opcode << 12; 512 1.10 christos while (is_whitespace (*op_end)) 513 1.1 christos op_end++; 514 1.1 christos if (*op_end != 0) 515 1.1 christos as_warn (_("extra stuff on line ignored")); 516 1.1 christos break; 517 1.1 christos case MOXIE_F3_PCREL: 518 1.1 christos iword = (3<<14) | (opcode->opcode << 10); 519 1.10 christos while (is_whitespace (*op_end)) 520 1.1 christos op_end++; 521 1.1 christos { 522 1.1 christos expressionS arg; 523 1.1 christos 524 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg); 525 1.1 christos fix_new_exp (frag_now, 526 1.1 christos (p - frag_now->fr_literal), 527 1.1 christos 2, 528 1.1 christos &arg, 529 1.8 christos true, 530 1.1 christos BFD_RELOC_MOXIE_10_PCREL); 531 1.1 christos } 532 1.1 christos break; 533 1.6 christos case MOXIE_BAD: 534 1.6 christos iword = 0; 535 1.10 christos while (is_whitespace (*op_end)) 536 1.6 christos op_end++; 537 1.6 christos if (*op_end != 0) 538 1.6 christos as_warn (_("extra stuff on line ignored")); 539 1.6 christos break; 540 1.1 christos default: 541 1.1 christos abort (); 542 1.1 christos } 543 1.1 christos 544 1.1 christos md_number_to_chars (p, iword, 2); 545 1.5 christos dwarf2_emit_insn (2); 546 1.1 christos 547 1.10 christos while (is_whitespace (*op_end)) 548 1.1 christos op_end++; 549 1.1 christos 550 1.1 christos if (*op_end != 0) 551 1.1 christos as_warn (_("extra stuff on line ignored")); 552 1.1 christos 553 1.1 christos if (pending_reloc) 554 1.1 christos as_bad (_("Something forgot to clean up\n")); 555 1.1 christos } 556 1.1 christos 557 1.1 christos /* Turn a string in input_line_pointer into a floating point constant 558 1.1 christos of type type, and store the appropriate bytes in *LITP. The number 559 1.1 christos of LITTLENUMS emitted is stored in *SIZEP . An error message is 560 1.1 christos returned, or NULL on OK. */ 561 1.1 christos 562 1.5 christos const char * 563 1.1 christos md_atof (int type, char *litP, int *sizeP) 564 1.1 christos { 565 1.1 christos int prec; 566 1.1 christos LITTLENUM_TYPE words[4]; 567 1.1 christos char *t; 568 1.1 christos int i; 569 1.1 christos 570 1.1 christos switch (type) 571 1.1 christos { 572 1.1 christos case 'f': 573 1.1 christos prec = 2; 574 1.1 christos break; 575 1.1 christos 576 1.1 christos case 'd': 577 1.1 christos prec = 4; 578 1.1 christos break; 579 1.1 christos 580 1.1 christos default: 581 1.1 christos *sizeP = 0; 582 1.1 christos return _("bad call to md_atof"); 583 1.1 christos } 584 1.1 christos 585 1.1 christos t = atof_ieee (input_line_pointer, type, words); 586 1.1 christos if (t) 587 1.1 christos input_line_pointer = t; 588 1.1 christos 589 1.1 christos *sizeP = prec * 2; 590 1.1 christos 591 1.1 christos for (i = prec - 1; i >= 0; i--) 592 1.1 christos { 593 1.10 christos md_number_to_chars (litP, words[i], 2); 594 1.1 christos litP += 2; 595 1.1 christos } 596 1.1 christos 597 1.1 christos return NULL; 598 1.1 christos } 599 1.3 christos 600 1.3 christos enum options 601 1.3 christos { 602 1.3 christos OPTION_EB = OPTION_MD_BASE, 603 1.3 christos OPTION_EL, 604 1.3 christos }; 605 1.1 christos 606 1.10 christos const struct option md_longopts[] = 607 1.1 christos { 608 1.3 christos { "EB", no_argument, NULL, OPTION_EB}, 609 1.3 christos { "EL", no_argument, NULL, OPTION_EL}, 610 1.3 christos { NULL, no_argument, NULL, 0} 611 1.1 christos }; 612 1.3 christos 613 1.10 christos const size_t md_longopts_size = sizeof (md_longopts); 614 1.3 christos 615 1.10 christos const char md_shortopts[] = ""; 617 1.1 christos 618 1.5 christos int 619 1.1 christos md_parse_option (int c ATTRIBUTE_UNUSED, const char *arg ATTRIBUTE_UNUSED) 620 1.3 christos { 621 1.3 christos switch (c) 622 1.3 christos { 623 1.3 christos case OPTION_EB: 624 1.3 christos target_big_endian = 1; 625 1.3 christos break; 626 1.3 christos case OPTION_EL: 627 1.3 christos target_big_endian = 0; 628 1.3 christos break; 629 1.3 christos default: 630 1.3 christos return 0; 631 1.3 christos } 632 1.3 christos 633 1.1 christos return 1; 634 1.1 christos } 635 1.1 christos 636 1.1 christos void 637 1.1 christos md_show_usage (FILE *stream ATTRIBUTE_UNUSED) 638 1.3 christos { 639 1.3 christos fprintf (stream, _("\ 640 1.3 christos -EB assemble for a big endian system (default)\n\ 641 1.1 christos -EL assemble for a little endian system\n")); 642 1.1 christos } 643 1.1 christos 644 1.1 christos /* Apply a fixup to the object file. */ 645 1.1 christos 646 1.3 christos void 647 1.1 christos md_apply_fix (fixS *fixP ATTRIBUTE_UNUSED, 648 1.1 christos valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED) 649 1.1 christos { 650 1.1 christos char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; 651 1.1 christos long val = *valP; 652 1.1 christos long newval; 653 1.1 christos long max, min; 654 1.1 christos 655 1.1 christos max = min = 0; 656 1.1 christos switch (fixP->fx_r_type) 657 1.1 christos { 658 1.3 christos case BFD_RELOC_32: 659 1.3 christos if (target_big_endian) 660 1.3 christos { 661 1.3 christos buf[0] = val >> 24; 662 1.3 christos buf[1] = val >> 16; 663 1.3 christos buf[2] = val >> 8; 664 1.3 christos buf[3] = val >> 0; 665 1.3 christos } 666 1.3 christos else 667 1.3 christos { 668 1.3 christos buf[3] = val >> 24; 669 1.3 christos buf[2] = val >> 16; 670 1.3 christos buf[1] = val >> 8; 671 1.3 christos buf[0] = val >> 0; 672 1.3 christos } 673 1.1 christos buf += 4; 674 1.1 christos break; 675 1.1 christos 676 1.3 christos case BFD_RELOC_16: 677 1.3 christos if (target_big_endian) 678 1.3 christos { 679 1.3 christos buf[0] = val >> 8; 680 1.3 christos buf[1] = val >> 0; 681 1.3 christos } 682 1.3 christos else 683 1.3 christos { 684 1.3 christos buf[1] = val >> 8; 685 1.3 christos buf[0] = val >> 0; 686 1.3 christos } 687 1.1 christos buf += 2; 688 1.1 christos break; 689 1.1 christos 690 1.1 christos case BFD_RELOC_8: 691 1.1 christos *buf++ = val; 692 1.1 christos break; 693 1.1 christos 694 1.1 christos case BFD_RELOC_MOXIE_10_PCREL: 695 1.1 christos if (!val) 696 1.1 christos break; 697 1.1 christos if (val < -1024 || val > 1022) 698 1.1 christos as_bad_where (fixP->fx_file, fixP->fx_line, 699 1.1 christos _("pcrel too far BFD_RELOC_MOXIE_10")); 700 1.1 christos /* 11 bit offset even numbered, so we remove right bit. */ 701 1.1 christos val >>= 1; 702 1.1 christos newval = md_chars_to_number (buf, 2); 703 1.1 christos newval |= val & 0x03ff; 704 1.1 christos md_number_to_chars (buf, newval, 2); 705 1.1 christos break; 706 1.1 christos 707 1.1 christos default: 708 1.1 christos abort (); 709 1.1 christos } 710 1.1 christos 711 1.1 christos if (max != 0 && (val < min || val > max)) 712 1.1 christos as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range")); 713 1.1 christos 714 1.1 christos if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) 715 1.1 christos fixP->fx_done = 1; 716 1.1 christos } 717 1.3 christos 718 1.1 christos /* Put number into target byte order. */ 719 1.1 christos 720 1.3 christos void 721 1.1 christos md_number_to_chars (char * ptr, valueT use, int nbytes) 722 1.3 christos { 723 1.3 christos if (target_big_endian) 724 1.3 christos number_to_chars_bigendian (ptr, use, nbytes); 725 1.3 christos else 726 1.1 christos number_to_chars_littleendian (ptr, use, nbytes); 727 1.1 christos } 728 1.1 christos 729 1.1 christos /* Convert from target byte order to host byte order. */ 730 1.3 christos 731 1.3 christos static valueT 732 1.1 christos md_chars_to_number (char * buf, int n) 733 1.3 christos { 734 1.1 christos valueT result = 0; 735 1.3 christos 736 1.3 christos if (target_big_endian) 737 1.3 christos { 738 1.3 christos while (n--) 739 1.3 christos { 740 1.10 christos result <<= 8; 741 1.3 christos result |= (*buf++ & 255); 742 1.3 christos } 743 1.3 christos } 744 1.1 christos else 745 1.3 christos { 746 1.3 christos while (n--) 747 1.3 christos { 748 1.10 christos result <<= 8; 749 1.3 christos result |= (buf[n] & 255); 750 1.1 christos } 751 1.1 christos } 752 1.3 christos 753 1.1 christos return result; 754 1.1 christos } 755 1.1 christos 756 1.1 christos /* Generate a machine-dependent relocation. */ 757 1.1 christos arelent * 758 1.1 christos tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP) 759 1.1 christos { 760 1.1 christos arelent *relP; 761 1.1 christos bfd_reloc_code_real_type code; 762 1.1 christos 763 1.1 christos switch (fixP->fx_r_type) 764 1.1 christos { 765 1.1 christos case BFD_RELOC_32: 766 1.1 christos code = fixP->fx_r_type; 767 1.1 christos break; 768 1.1 christos case BFD_RELOC_MOXIE_10_PCREL: 769 1.1 christos code = fixP->fx_r_type; 770 1.1 christos break; 771 1.1 christos default: 772 1.1 christos as_bad_where (fixP->fx_file, fixP->fx_line, 773 1.1 christos _("Semantics error. This type of operand can not be relocated, it must be an assembly-time constant")); 774 1.1 christos return 0; 775 1.1 christos } 776 1.10 christos 777 1.10 christos relP = notes_alloc (sizeof (arelent)); 778 1.1 christos relP->sym_ptr_ptr = notes_alloc (sizeof (asymbol *)); 779 1.1 christos *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy); 780 1.1 christos relP->address = fixP->fx_frag->fr_address + fixP->fx_where; 781 1.1 christos 782 1.1 christos relP->addend = fixP->fx_offset; 783 1.1 christos 784 1.1 christos /* This is the standard place for KLUDGEs to work around bugs in 785 1.1 christos bfd_install_relocation (first such note in the documentation 786 1.1 christos appears with binutils-2.8). 787 1.1 christos 788 1.1 christos That function bfd_install_relocation does the wrong thing with 789 1.1 christos putting stuff into the addend of a reloc (it should stay out) for a 790 1.1 christos weak symbol. The really bad thing is that it adds the 791 1.1 christos "segment-relative offset" of the symbol into the reloc. In this 792 1.1 christos case, the reloc should instead be relative to the symbol with no 793 1.1 christos other offset than the assembly code shows; and since the symbol is 794 1.1 christos weak, any local definition should be ignored until link time (or 795 1.1 christos thereafter). 796 1.1 christos To wit: weaksym+42 should be weaksym+42 in the reloc, 797 1.1 christos not weaksym+(offset_from_segment_of_local_weaksym_definition) 798 1.1 christos 799 1.1 christos To "work around" this, we subtract the segment-relative offset of 800 1.1 christos "known" weak symbols. This evens out the extra offset. 801 1.1 christos 802 1.1 christos That happens for a.out but not for ELF, since for ELF, 803 1.1 christos bfd_install_relocation uses the "special function" field of the 804 1.1 christos howto, and does not execute the code that needs to be undone. */ 805 1.1 christos 806 1.1 christos if (OUTPUT_FLAVOR == bfd_target_aout_flavour 807 1.1 christos && fixP->fx_addsy && S_IS_WEAK (fixP->fx_addsy) 808 1.1 christos && ! bfd_is_und_section (S_GET_SEGMENT (fixP->fx_addsy))) 809 1.1 christos { 810 1.1 christos relP->addend -= S_GET_VALUE (fixP->fx_addsy); 811 1.1 christos } 812 1.1 christos 813 1.1 christos relP->howto = bfd_reloc_type_lookup (stdoutput, code); 814 1.1 christos if (! relP->howto) 815 1.1 christos { 816 1.1 christos const char *name; 817 1.1 christos 818 1.1 christos name = S_GET_NAME (fixP->fx_addsy); 819 1.1 christos if (name == NULL) 820 1.1 christos name = _("<unknown>"); 821 1.1 christos as_fatal (_("Cannot generate relocation type for symbol %s, code %s"), 822 1.1 christos name, bfd_get_reloc_code_name (code)); 823 1.1 christos } 824 1.1 christos 825 1.1 christos return relP; 826 1.1 christos } 827 1.1 christos 828 1.1 christos /* Decide from what point a pc-relative relocation is relative to, 829 1.1 christos relative to the pc-relative fixup. Er, relatively speaking. */ 830 1.1 christos long 831 1.1 christos md_pcrel_from (fixS *fixP) 832 1.1 christos { 833 1.1 christos valueT addr = fixP->fx_where + fixP->fx_frag->fr_address; 834 1.1 christos 835 1.1 christos switch (fixP->fx_r_type) 836 1.1 christos { 837 1.1 christos case BFD_RELOC_32: 838 1.1 christos return addr + 4; 839 1.3 christos case BFD_RELOC_MOXIE_10_PCREL: 840 1.3 christos /* Offset is from the end of the instruction. */ 841 1.1 christos return addr + 2; 842 1.1 christos default: 843 1.1 christos abort (); 844 1.1 christos return addr; 845 1.1 christos } 846 } 847