1 /*- 2 tc-pj.c -- Assemble code for Pico Java 3 Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. 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 2, 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 19 the Free Software Foundation, 59 Temple Place - Suite 330, 20 Boston, MA 02111-1307, USA. */ 21 22 /* Contributed by Steve Chamberlain of Transmeta <sac@pobox.com>. */ 23 24 #include "as.h" 25 #include "safe-ctype.h" 26 #include "opcode/pj.h" 27 28 extern const pj_opc_info_t pj_opc_info[512]; 29 30 const char comment_chars[] = "!/"; 31 const char line_separator_chars[] = ";"; 32 const char line_comment_chars[] = "/!#"; 33 34 static int pending_reloc; 35 static struct hash_control *opcode_hash_control; 36 37 static void little 38 PARAMS ((int)); 39 static void big 40 PARAMS ((int)); 41 static char *parse_exp_save_ilp 42 PARAMS ((char *, expressionS *)); 43 static int c_to_r 44 PARAMS ((char)); 45 static void ipush_code 46 PARAMS ((pj_opc_info_t *, char *)); 47 static void fake_opcode 48 PARAMS ((const char *, void (*) (struct pj_opc_info_t *, char *))); 49 static void alias 50 PARAMS ((const char *, const char *)); 51 52 static void 53 little (ignore) 54 int ignore ATTRIBUTE_UNUSED; 55 { 56 target_big_endian = 0; 57 } 58 59 static void 60 big (ignore) 61 int ignore ATTRIBUTE_UNUSED; 62 { 63 target_big_endian = 1; 64 } 65 66 const pseudo_typeS md_pseudo_table[] = { 67 {"ml", little, 0}, 68 {"mb", big, 0}, 69 {0, 0, 0} 70 }; 71 72 const char FLT_CHARS[] = "rRsSfFdDxXpP"; 73 const char EXP_CHARS[] = "eE"; 74 75 void 76 md_operand (op) 77 expressionS *op; 78 { 79 if (strncmp (input_line_pointer, "%hi16", 5) == 0) 80 { 81 if (pending_reloc) 82 as_bad (_("confusing relocation expressions")); 83 pending_reloc = BFD_RELOC_PJ_CODE_HI16; 84 input_line_pointer += 5; 85 expression (op); 86 } 87 if (strncmp (input_line_pointer, "%lo16", 5) == 0) 88 { 89 if (pending_reloc) 90 as_bad (_("confusing relocation expressions")); 91 pending_reloc = BFD_RELOC_PJ_CODE_LO16; 92 input_line_pointer += 5; 93 expression (op); 94 } 95 } 96 97 /* Parse an expression and then restore the input line pointer. */ 98 99 static char * 100 parse_exp_save_ilp (s, op) 101 char *s; 102 expressionS *op; 103 { 104 char *save = input_line_pointer; 105 input_line_pointer = s; 106 expression (op); 107 s = input_line_pointer; 108 input_line_pointer = save; 109 return s; 110 } 111 112 /* This is called by emit_expr via TC_CONS_FIX_NEW when creating a 113 reloc for a cons. We could use the definition there, except that 114 we want to handle magic pending reloc expressions specially. */ 115 116 void 117 pj_cons_fix_new_pj (frag, where, nbytes, exp) 118 fragS *frag; 119 int where; 120 int nbytes; 121 expressionS *exp; 122 { 123 static int rv[5][2] = 124 { { 0, 0 }, 125 { BFD_RELOC_8, BFD_RELOC_8 }, 126 { BFD_RELOC_PJ_CODE_DIR16, BFD_RELOC_16 }, 127 { 0, 0 }, 128 { BFD_RELOC_PJ_CODE_DIR32, BFD_RELOC_32 }}; 129 130 fix_new_exp (frag, where, nbytes, exp, 0, 131 pending_reloc ? pending_reloc 132 : rv[nbytes][(now_seg->flags & SEC_CODE) ? 0 : 1]); 133 134 pending_reloc = 0; 135 } 136 137 /* Turn a reloc description character from the pj-opc.h table into 138 code which BFD can handle. */ 139 140 static int 141 c_to_r (x) 142 char x; 143 { 144 switch (x) 145 { 146 case O_R8: 147 return BFD_RELOC_8_PCREL; 148 case O_U8: 149 case O_8: 150 return BFD_RELOC_8; 151 case O_R16: 152 return BFD_RELOC_PJ_CODE_REL16; 153 case O_U16: 154 case O_16: 155 return BFD_RELOC_PJ_CODE_DIR16; 156 case O_R32: 157 return BFD_RELOC_PJ_CODE_REL32; 158 case O_32: 159 return BFD_RELOC_PJ_CODE_DIR32; 160 } 161 abort (); 162 return 0; 163 } 164 165 /* Handler for the ipush fake opcode, 166 turns ipush <foo> into sipush lo16<foo>, sethi hi16<foo>. */ 167 168 static void 169 ipush_code (opcode, str) 170 pj_opc_info_t *opcode ATTRIBUTE_UNUSED; 171 char *str; 172 { 173 char *b = frag_more (6); 174 expressionS arg; 175 176 b[0] = 0x11; 177 b[3] = 0xed; 178 parse_exp_save_ilp (str + 1, &arg); 179 if (pending_reloc) 180 { 181 as_bad (_("can't have relocation for ipush")); 182 pending_reloc = 0; 183 } 184 185 fix_new_exp (frag_now, b - frag_now->fr_literal + 1, 2, 186 &arg, 0, BFD_RELOC_PJ_CODE_DIR16); 187 fix_new_exp (frag_now, b - frag_now->fr_literal + 4, 2, 188 &arg, 0, BFD_RELOC_PJ_CODE_HI16); 189 } 190 191 /* Insert names into the opcode table which are really mini macros, 192 not opcodes. The fakeness is indicated with an opcode of -1. */ 193 194 static void 195 fake_opcode (name, func) 196 const char *name; 197 void (*func) PARAMS ((struct pj_opc_info_t *, char *)); 198 { 199 pj_opc_info_t *fake = (pj_opc_info_t *) xmalloc (sizeof (pj_opc_info_t)); 200 201 fake->opcode = -1; 202 fake->opcode_next = -1; 203 fake->u.func = func; 204 hash_insert (opcode_hash_control, name, (char *) fake); 205 } 206 207 /* Enter another entry into the opcode hash table so the same opcode 208 can have another name. */ 209 210 static void 211 alias (new, old) 212 const char *new; 213 const char *old; 214 { 215 hash_insert (opcode_hash_control, new, 216 (char *) hash_find (opcode_hash_control, old)); 217 } 218 219 /* This function is called once, at assembler startup time. It sets 220 up the hash table with all the opcodes in it, and also initializes 221 some aliases for compatibility with other assemblers. */ 222 223 void 224 md_begin () 225 { 226 const pj_opc_info_t *opcode; 227 opcode_hash_control = hash_new (); 228 229 /* Insert names into hash table. */ 230 for (opcode = pj_opc_info; opcode->u.name; opcode++) 231 hash_insert (opcode_hash_control, opcode->u.name, (char *) opcode); 232 233 /* Insert the only fake opcode. */ 234 fake_opcode ("ipush", ipush_code); 235 236 /* Add some aliases for opcode names. */ 237 alias ("ifeq_s", "ifeq"); 238 alias ("ifne_s", "ifne"); 239 alias ("if_icmpge_s", "if_icmpge"); 240 alias ("if_icmpne_s", "if_icmpne"); 241 alias ("if_icmpeq_s", "if_icmpeq"); 242 alias ("if_icmpgt_s", "if_icmpgt"); 243 alias ("goto_s", "goto"); 244 245 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0); 246 } 247 248 /* This is the guts of the machine-dependent assembler. STR points to 249 a machine dependent instruction. This function is supposed to emit 250 the frags/bytes it assembles to. */ 251 252 void 253 md_assemble (str) 254 char *str; 255 { 256 unsigned char *op_start; 257 unsigned char *op_end; 258 259 #if 0 260 pj_operan_info operand[3]; 261 #endif 262 pj_opc_info_t *opcode; 263 char *output; 264 int idx = 0; 265 char pend; 266 267 int nlen = 0; 268 269 /* Drop leading whitespace. */ 270 while (*str == ' ') 271 str++; 272 273 /* Find the op code end. */ 274 for (op_start = op_end = (unsigned char *) (str); 275 *op_end && !is_end_of_line[*op_end] && *op_end != ' '; 276 op_end++) 277 nlen++; 278 279 pend = *op_end; 280 *op_end = 0; 281 282 if (nlen == 0) 283 as_bad (_("can't find opcode ")); 284 285 opcode = (pj_opc_info_t *) hash_find (opcode_hash_control, op_start); 286 *op_end = pend; 287 288 if (opcode == NULL) 289 { 290 as_bad (_("unknown opcode %s"), op_start); 291 return; 292 } 293 294 if (opcode->opcode == -1) 295 { 296 /* It's a fake opcode. Dig out the args and pretend that was 297 what we were passed. */ 298 (*opcode->u.func) (opcode, op_end); 299 } 300 else 301 { 302 int an; 303 304 output = frag_more (opcode->len); 305 output[idx++] = opcode->opcode; 306 307 if (opcode->opcode_next != -1) 308 output[idx++] = opcode->opcode_next; 309 310 for (an = 0; opcode->arg[an]; an++) 311 { 312 expressionS arg; 313 314 if (*op_end == ',' && an != 0) 315 op_end++; 316 317 if (*op_end == 0) 318 as_bad ("expected expresssion"); 319 320 op_end = parse_exp_save_ilp (op_end, &arg); 321 322 fix_new_exp (frag_now, 323 output - frag_now->fr_literal + idx, 324 ASIZE (opcode->arg[an]), 325 &arg, 326 PCREL (opcode->arg[an]), 327 pending_reloc ? pending_reloc : c_to_r (opcode->arg[an])); 328 329 idx += ASIZE (opcode->arg[an]); 330 pending_reloc = 0; 331 } 332 333 while (ISSPACE (*op_end)) 334 op_end++; 335 336 if (*op_end != 0) 337 as_warn ("extra stuff on line ignored"); 338 339 } 340 341 if (pending_reloc) 342 as_bad ("Something forgot to clean up\n"); 343 344 } 345 346 /* Turn a string in input_line_pointer into a floating point constant 347 of type type, and store the appropriate bytes in *LITP. The number 348 of LITTLENUMS emitted is stored in *SIZEP . An error message is 349 returned, or NULL on OK. */ 350 351 char * 352 md_atof (type, litP, sizeP) 353 int type; 354 char *litP; 355 int *sizeP; 356 { 357 int prec; 358 LITTLENUM_TYPE words[4]; 359 char *t; 360 int i; 361 362 switch (type) 363 { 364 case 'f': 365 prec = 2; 366 break; 367 368 case 'd': 369 prec = 4; 370 break; 371 372 default: 373 *sizeP = 0; 374 return _("bad call to md_atof"); 375 } 376 377 t = atof_ieee (input_line_pointer, type, words); 378 if (t) 379 input_line_pointer = t; 380 381 *sizeP = prec * 2; 382 383 if (!target_big_endian) 384 { 385 for (i = prec - 1; i >= 0; i--) 386 { 387 md_number_to_chars (litP, (valueT) words[i], 2); 388 litP += 2; 389 } 390 } 391 else 392 { 393 for (i = 0; i < prec; i++) 394 { 395 md_number_to_chars (litP, (valueT) words[i], 2); 396 litP += 2; 397 } 398 } 399 400 return NULL; 401 } 402 403 const char *md_shortopts = ""; 404 405 struct option md_longopts[] = { 406 407 #define OPTION_LITTLE (OPTION_MD_BASE) 408 #define OPTION_BIG (OPTION_LITTLE + 1) 409 410 {"little", no_argument, NULL, OPTION_LITTLE}, 411 {"big", no_argument, NULL, OPTION_BIG}, 412 {NULL, no_argument, NULL, 0} 413 }; 414 size_t md_longopts_size = sizeof (md_longopts); 415 416 int 417 md_parse_option (c, arg) 418 int c; 419 char *arg ATTRIBUTE_UNUSED; 420 { 421 switch (c) 422 { 423 case OPTION_LITTLE: 424 little (0); 425 break; 426 case OPTION_BIG: 427 big (0); 428 break; 429 default: 430 return 0; 431 } 432 return 1; 433 } 434 435 void 436 md_show_usage (stream) 437 FILE *stream; 438 { 439 fprintf (stream, _("\ 440 PJ options:\n\ 441 -little generate little endian code\n\ 442 -big generate big endian code\n")); 443 } 444 445 /* Apply a fixup to the object file. */ 446 447 void 448 md_apply_fix3 (fixP, valP, seg) 449 fixS *fixP; 450 valueT * valP; 451 segT seg ATTRIBUTE_UNUSED; 452 { 453 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; 454 long val = *valP; 455 long max, min; 456 int shift; 457 458 max = min = 0; 459 shift = 0; 460 switch (fixP->fx_r_type) 461 { 462 case BFD_RELOC_VTABLE_INHERIT: 463 case BFD_RELOC_VTABLE_ENTRY: 464 fixP->fx_done = 0; 465 return; 466 467 case BFD_RELOC_PJ_CODE_REL16: 468 if (val < -0x8000 || val >= 0x7fff) 469 as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far")); 470 buf[0] |= (val >> 8) & 0xff; 471 buf[1] = val & 0xff; 472 break; 473 474 case BFD_RELOC_PJ_CODE_HI16: 475 *buf++ = val >> 24; 476 *buf++ = val >> 16; 477 fixP->fx_addnumber = val & 0xffff; 478 break; 479 480 case BFD_RELOC_PJ_CODE_DIR16: 481 case BFD_RELOC_PJ_CODE_LO16: 482 *buf++ = val >> 8; 483 *buf++ = val >> 0; 484 485 max = 0xffff; 486 min = -0xffff; 487 break; 488 489 case BFD_RELOC_8: 490 max = 0xff; 491 min = -0xff; 492 *buf++ = val; 493 break; 494 495 case BFD_RELOC_PJ_CODE_DIR32: 496 *buf++ = val >> 24; 497 *buf++ = val >> 16; 498 *buf++ = val >> 8; 499 *buf++ = val >> 0; 500 break; 501 502 case BFD_RELOC_32: 503 if (target_big_endian) 504 { 505 *buf++ = val >> 24; 506 *buf++ = val >> 16; 507 *buf++ = val >> 8; 508 *buf++ = val >> 0; 509 } 510 else 511 { 512 *buf++ = val >> 0; 513 *buf++ = val >> 8; 514 *buf++ = val >> 16; 515 *buf++ = val >> 24; 516 } 517 break; 518 519 case BFD_RELOC_16: 520 if (target_big_endian) 521 { 522 *buf++ = val >> 8; 523 *buf++ = val >> 0; 524 } 525 else 526 { 527 *buf++ = val >> 0; 528 *buf++ = val >> 8; 529 } 530 break; 531 532 default: 533 abort (); 534 } 535 536 if (max != 0 && (val < min || val > max)) 537 as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range")); 538 539 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) 540 fixP->fx_done = 1; 541 } 542 543 /* Put number into target byte order. Always put values in an 544 executable section into big endian order. */ 545 546 void 547 md_number_to_chars (ptr, use, nbytes) 548 char *ptr; 549 valueT use; 550 int nbytes; 551 { 552 if (target_big_endian || now_seg->flags & SEC_CODE) 553 number_to_chars_bigendian (ptr, use, nbytes); 554 else 555 number_to_chars_littleendian (ptr, use, nbytes); 556 } 557 558 /* Translate internal representation of relocation info to BFD target 559 format. */ 560 561 arelent * 562 tc_gen_reloc (section, fixp) 563 asection *section ATTRIBUTE_UNUSED; 564 fixS *fixp; 565 { 566 arelent *rel; 567 bfd_reloc_code_real_type r_type; 568 569 rel = (arelent *) xmalloc (sizeof (arelent)); 570 rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); 571 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); 572 rel->address = fixp->fx_frag->fr_address + fixp->fx_where; 573 574 r_type = fixp->fx_r_type; 575 rel->addend = fixp->fx_addnumber; 576 rel->howto = bfd_reloc_type_lookup (stdoutput, r_type); 577 578 if (rel->howto == NULL) 579 { 580 as_bad_where (fixp->fx_file, fixp->fx_line, 581 _("Cannot represent relocation type %s"), 582 bfd_get_reloc_code_name (r_type)); 583 /* Set howto to a garbage value so that we can keep going. */ 584 rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32); 585 assert (rel->howto != NULL); 586 } 587 588 return rel; 589 } 590