1/* tc-mep.c -- Assembler for the Toshiba Media Processor. 2 Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation. 3 4 This file is part of GAS, the GNU Assembler. 5 6 GAS is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GAS is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GAS; see the file COPYING. If not, write to 18 the Free Software Foundation, 51 Franklin Street, Fifth Floor, 19 Boston, MA 02110-1301, USA. */ 20 21#include <stdio.h> 22#include "as.h" 23#include "dwarf2dbg.h" 24#include "subsegs.h" 25#include "symcat.h" 26#include "opcodes/mep-desc.h" 27#include "opcodes/mep-opc.h" 28#include "cgen.h" 29#include "elf/common.h" 30#include "elf/mep.h" 31#include "libbfd.h" 32#include "xregex.h" 33 34/* Structure to hold all of the different components describing 35 an individual instruction. */ 36typedef struct 37{ 38 const CGEN_INSN * insn; 39 const CGEN_INSN * orig_insn; 40 CGEN_FIELDS fields; 41#if CGEN_INT_INSN_P 42 CGEN_INSN_INT buffer [1]; 43#define INSN_VALUE(buf) (*(buf)) 44#else 45 unsigned char buffer [CGEN_MAX_INSN_SIZE]; 46#define INSN_VALUE(buf) (buf) 47#endif 48 char * addr; 49 fragS * frag; 50 int num_fixups; 51 fixS * fixups [GAS_CGEN_MAX_FIXUPS]; 52 int indices [MAX_OPERAND_INSTANCES]; 53} mep_insn; 54 55static int mode = CORE; /* Start in core mode. */ 56static int pluspresent = 0; 57static int allow_disabled_registers = 0; 58static int library_flag = 0; 59 60/* We're going to need to store all of the instructions along with 61 their fixups so that we can parallelization grouping rules. */ 62 63static mep_insn saved_insns[MAX_SAVED_FIXUP_CHAINS]; 64static int num_insns_saved = 0; 65 66const char comment_chars[] = "#"; 67const char line_comment_chars[] = ";#"; 68const char line_separator_chars[] = ";"; 69const char EXP_CHARS[] = "eE"; 70const char FLT_CHARS[] = "dD"; 71 72static void mep_switch_to_vliw_mode (int); 73static void mep_switch_to_core_mode (int); 74static void mep_s_vtext (int); 75static void mep_noregerr (int); 76 77/* The target specific pseudo-ops which we support. */ 78const pseudo_typeS md_pseudo_table[] = 79{ 80 { "word", cons, 4 }, 81 { "file", (void (*) (int)) dwarf2_directive_file, 0 }, 82 { "loc", dwarf2_directive_loc, 0 }, 83 { "vliw", mep_switch_to_vliw_mode, 0 }, 84 { "core", mep_switch_to_core_mode, 0 }, 85 { "vtext", mep_s_vtext, 0 }, 86 { "noregerr", mep_noregerr, 0 }, 87 { NULL, NULL, 0 } 88}; 89 90/* Relocations against symbols are done in two 91 parts, with a HI relocation and a LO relocation. Each relocation 92 has only 16 bits of space to store an addend. This means that in 93 order for the linker to handle carries correctly, it must be able 94 to locate both the HI and the LO relocation. This means that the 95 relocations must appear in order in the relocation table. 96 97 In order to implement this, we keep track of each unmatched HI 98 relocation. We then sort them so that they immediately precede the 99 corresponding LO relocation. */ 100 101struct mep_hi_fixup 102{ 103 struct mep_hi_fixup * next; /* Next HI fixup. */ 104 fixS * fixp; /* This fixup. */ 105 segT seg; /* The section this fixup is in. */ 106}; 107 108/* The list of unmatched HI relocs. */ 109static struct mep_hi_fixup * mep_hi_fixup_list; 110 111 112#define OPTION_EB (OPTION_MD_BASE + 0) 113#define OPTION_EL (OPTION_MD_BASE + 1) 114#define OPTION_CONFIG (OPTION_MD_BASE + 2) 115#define OPTION_AVERAGE (OPTION_MD_BASE + 3) 116#define OPTION_NOAVERAGE (OPTION_MD_BASE + 4) 117#define OPTION_MULT (OPTION_MD_BASE + 5) 118#define OPTION_NOMULT (OPTION_MD_BASE + 6) 119#define OPTION_DIV (OPTION_MD_BASE + 7) 120#define OPTION_NODIV (OPTION_MD_BASE + 8) 121#define OPTION_BITOPS (OPTION_MD_BASE + 9) 122#define OPTION_NOBITOPS (OPTION_MD_BASE + 10) 123#define OPTION_LEADZ (OPTION_MD_BASE + 11) 124#define OPTION_NOLEADZ (OPTION_MD_BASE + 12) 125#define OPTION_ABSDIFF (OPTION_MD_BASE + 13) 126#define OPTION_NOABSDIFF (OPTION_MD_BASE + 14) 127#define OPTION_MINMAX (OPTION_MD_BASE + 15) 128#define OPTION_NOMINMAX (OPTION_MD_BASE + 16) 129#define OPTION_CLIP (OPTION_MD_BASE + 17) 130#define OPTION_NOCLIP (OPTION_MD_BASE + 18) 131#define OPTION_SATUR (OPTION_MD_BASE + 19) 132#define OPTION_NOSATUR (OPTION_MD_BASE + 20) 133#define OPTION_COP32 (OPTION_MD_BASE + 21) 134#define OPTION_REPEAT (OPTION_MD_BASE + 25) 135#define OPTION_NOREPEAT (OPTION_MD_BASE + 26) 136#define OPTION_DEBUG (OPTION_MD_BASE + 27) 137#define OPTION_NODEBUG (OPTION_MD_BASE + 28) 138#define OPTION_LIBRARY (OPTION_MD_BASE + 29) 139 140struct option md_longopts[] = { 141 { "EB", no_argument, NULL, OPTION_EB}, 142 { "EL", no_argument, NULL, OPTION_EL}, 143 { "mconfig", required_argument, NULL, OPTION_CONFIG}, 144 { "maverage", no_argument, NULL, OPTION_AVERAGE}, 145 { "mno-average", no_argument, NULL, OPTION_NOAVERAGE}, 146 { "mmult", no_argument, NULL, OPTION_MULT}, 147 { "mno-mult", no_argument, NULL, OPTION_NOMULT}, 148 { "mdiv", no_argument, NULL, OPTION_DIV}, 149 { "mno-div", no_argument, NULL, OPTION_NODIV}, 150 { "mbitops", no_argument, NULL, OPTION_BITOPS}, 151 { "mno-bitops", no_argument, NULL, OPTION_NOBITOPS}, 152 { "mleadz", no_argument, NULL, OPTION_LEADZ}, 153 { "mno-leadz", no_argument, NULL, OPTION_NOLEADZ}, 154 { "mabsdiff", no_argument, NULL, OPTION_ABSDIFF}, 155 { "mno-absdiff", no_argument, NULL, OPTION_NOABSDIFF}, 156 { "mminmax", no_argument, NULL, OPTION_MINMAX}, 157 { "mno-minmax", no_argument, NULL, OPTION_NOMINMAX}, 158 { "mclip", no_argument, NULL, OPTION_CLIP}, 159 { "mno-clip", no_argument, NULL, OPTION_NOCLIP}, 160 { "msatur", no_argument, NULL, OPTION_SATUR}, 161 { "mno-satur", no_argument, NULL, OPTION_NOSATUR}, 162 { "mcop32", no_argument, NULL, OPTION_COP32}, 163 { "mdebug", no_argument, NULL, OPTION_DEBUG}, 164 { "mno-debug", no_argument, NULL, OPTION_NODEBUG}, 165 { "mlibrary", no_argument, NULL, OPTION_LIBRARY}, 166 { NULL, 0, NULL, 0 } }; 167size_t md_longopts_size = sizeof (md_longopts); 168 169const char * md_shortopts = ""; 170static int optbits = 0; 171static int optbitset = 0; 172 173int 174md_parse_option (int c, char *arg ATTRIBUTE_UNUSED) 175{ 176 int i, idx; 177 switch (c) 178 { 179 case OPTION_EB: 180 target_big_endian = 1; 181 break; 182 case OPTION_EL: 183 target_big_endian = 0; 184 break; 185 case OPTION_CONFIG: 186 idx = 0; 187 for (i=1; mep_config_map[i].name; i++) 188 if (strcmp (mep_config_map[i].name, arg) == 0) 189 { 190 idx = i; 191 break; 192 } 193 if (!idx) 194 { 195 fprintf (stderr, "Error: unknown configuration %s\n", arg); 196 return 0; 197 } 198 mep_config_index = idx; 199 target_big_endian = mep_config_map[idx].big_endian; 200 break; 201 case OPTION_AVERAGE: 202 optbits |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN; 203 optbitset |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN; 204 break; 205 case OPTION_NOAVERAGE: 206 optbits &= ~(1 << CGEN_INSN_OPTIONAL_AVE_INSN); 207 optbitset |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN; 208 break; 209 case OPTION_MULT: 210 optbits |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN; 211 optbitset |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN; 212 break; 213 case OPTION_NOMULT: 214 optbits &= ~(1 << CGEN_INSN_OPTIONAL_MUL_INSN); 215 optbitset |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN; 216 break; 217 case OPTION_DIV: 218 optbits |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN; 219 optbitset |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN; 220 break; 221 case OPTION_NODIV: 222 optbits &= ~(1 << CGEN_INSN_OPTIONAL_DIV_INSN); 223 optbitset |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN; 224 break; 225 case OPTION_BITOPS: 226 optbits |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN; 227 optbitset |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN; 228 break; 229 case OPTION_NOBITOPS: 230 optbits &= ~(1 << CGEN_INSN_OPTIONAL_BIT_INSN); 231 optbitset |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN; 232 break; 233 case OPTION_LEADZ: 234 optbits |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN; 235 optbitset |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN; 236 break; 237 case OPTION_NOLEADZ: 238 optbits &= ~(1 << CGEN_INSN_OPTIONAL_LDZ_INSN); 239 optbitset |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN; 240 break; 241 case OPTION_ABSDIFF: 242 optbits |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN; 243 optbitset |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN; 244 break; 245 case OPTION_NOABSDIFF: 246 optbits &= ~(1 << CGEN_INSN_OPTIONAL_ABS_INSN); 247 optbitset |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN; 248 break; 249 case OPTION_MINMAX: 250 optbits |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN; 251 optbitset |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN; 252 break; 253 case OPTION_NOMINMAX: 254 optbits &= ~(1 << CGEN_INSN_OPTIONAL_MINMAX_INSN); 255 optbitset |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN; 256 break; 257 case OPTION_CLIP: 258 optbits |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN; 259 optbitset |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN; 260 break; 261 case OPTION_NOCLIP: 262 optbits &= ~(1 << CGEN_INSN_OPTIONAL_CLIP_INSN); 263 optbitset |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN; 264 break; 265 case OPTION_SATUR: 266 optbits |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN; 267 optbitset |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN; 268 break; 269 case OPTION_NOSATUR: 270 optbits &= ~(1 << CGEN_INSN_OPTIONAL_SAT_INSN); 271 optbitset |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN; 272 break; 273 case OPTION_COP32: 274 optbits |= 1 << CGEN_INSN_OPTIONAL_CP_INSN; 275 optbitset |= 1 << CGEN_INSN_OPTIONAL_CP_INSN; 276 break; 277 case OPTION_DEBUG: 278 optbits |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN; 279 optbitset |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN; 280 break; 281 case OPTION_NODEBUG: 282 optbits &= ~(1 << CGEN_INSN_OPTIONAL_DEBUG_INSN); 283 optbitset |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN; 284 break; 285 case OPTION_LIBRARY: 286 library_flag = EF_MEP_LIBRARY; 287 break; 288 case OPTION_REPEAT: 289 case OPTION_NOREPEAT: 290 break; 291 default: 292 return 0; 293 } 294 return 1; 295} 296 297void 298md_show_usage (FILE *stream) 299{ 300 fprintf (stream, _("MeP specific command line options:\n\ 301 -EB assemble for a big endian system (default)\n\ 302 -EL assemble for a little endian system\n\ 303 -mconfig=<name> specify a chip configuration to use\n\ 304 -maverage -mno-average -mmult -mno-mult -mdiv -mno-div\n\ 305 -mbitops -mno-bitops -mleadz -mno-leadz -mabsdiff -mno-absdiff\n\ 306 -mminmax -mno-minmax -mclip -mno-clip -msatur -mno-satur -mcop32\n\ 307 enable/disable the given opcodes\n\ 308\n\ 309 If -mconfig is given, the other -m options modify it. Otherwise,\n\ 310 if no -m options are given, all core opcodes are enabled;\n\ 311 if any enabling -m options are given, only those are enabled;\n\ 312 if only disabling -m options are given, only those are disabled.\n\ 313")); 314 if (mep_config_map[1].name) 315 { 316 int i; 317 fprintf (stream, " -mconfig=STR specify the configuration to use\n"); 318 fprintf (stream, " Configurations:"); 319 for (i=0; mep_config_map[i].name; i++) 320 fprintf (stream, " %s", mep_config_map[i].name); 321 fprintf (stream, "\n"); 322 } 323} 324 325 326 327static void 328mep_check_for_disabled_registers (mep_insn *insn) 329{ 330 static int initted = 0; 331 static int has_mul_div = 0; 332 static int has_cop = 0; 333 static int has_debug = 0; 334 unsigned int b, r; 335 336 if (allow_disabled_registers) 337 return; 338 339#if !CGEN_INT_INSN_P 340 if (target_big_endian) 341 b = insn->buffer[0] * 256 + insn->buffer[1]; 342 else 343 b = insn->buffer[1] * 256 + insn->buffer[0]; 344#else 345 b = insn->buffer[0]; 346#endif 347 348 if ((b & 0xfffff00e) == 0x7008 /* stc */ 349 || (b & 0xfffff00e) == 0x700a /* ldc */) 350 { 351 if (!initted) 352 { 353 initted = 1; 354 if ((MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_MUL_INSN)) 355 || (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_DIV_INSN))) 356 has_mul_div = 1; 357 if (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN)) 358 has_debug = 1; 359 if (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_CP_INSN)) 360 has_cop = 1; 361 } 362 363 r = ((b & 0x00f0) >> 4) | ((b & 0x0001) << 4); 364 switch (r) 365 { 366 case 7: /* $hi */ 367 case 8: /* $lo */ 368 if (!has_mul_div) 369 as_bad ("$hi and $lo are disabled when MUL and DIV are off"); 370 break; 371 case 12: /* $mb0 */ 372 case 13: /* $me0 */ 373 case 14: /* $mb1 */ 374 case 15: /* $me1 */ 375 if (!has_cop) 376 as_bad ("$mb0, $me0, $mb1, and $me1 are disabled when COP is off"); 377 break; 378 case 24: /* $dbg */ 379 case 25: /* $depc */ 380 if (!has_debug) 381 as_bad ("$dbg and $depc are disabled when DEBUG is off"); 382 break; 383 } 384 } 385} 386 387static int 388mep_machine (void) 389{ 390 switch (MEP_CPU) 391 { 392 default: break; 393 case EF_MEP_CPU_C2: return bfd_mach_mep; 394 case EF_MEP_CPU_C3: return bfd_mach_mep; 395 case EF_MEP_CPU_C4: return bfd_mach_mep; 396 case EF_MEP_CPU_H1: return bfd_mach_mep_h1; 397 } 398 399 return bfd_mach_mep; 400} 401 402/* The MeP version of the cgen parse_operand function. The only difference 403 from the standard version is that we want to avoid treating '$foo' and 404 '($foo...)' as references to a symbol called '$foo'. The chances are 405 that '$foo' is really a misspelt register. */ 406 407static const char * 408mep_parse_operand (CGEN_CPU_DESC cd, enum cgen_parse_operand_type want, 409 const char **strP, int opindex, int opinfo, 410 enum cgen_parse_operand_result *resultP, bfd_vma *valueP) 411{ 412 if (want == CGEN_PARSE_OPERAND_INTEGER || want == CGEN_PARSE_OPERAND_ADDRESS) 413 { 414 const char *next; 415 416 next = *strP; 417 while (*next == '(') 418 next++; 419 if (*next == '$') 420 return "Not a valid literal"; 421 } 422 return gas_cgen_parse_operand (cd, want, strP, opindex, opinfo, 423 resultP, valueP); 424} 425 426void 427md_begin () 428{ 429 /* Initialize the `cgen' interface. */ 430 431 /* If the user specifies no options, we default to allowing 432 everything. If the user specifies any enabling options, we 433 default to allowing only what is specified. If the user 434 specifies only disabling options, we only disable what is 435 specified. If the user specifies options and a config, the 436 options modify the config. */ 437 if (optbits && mep_config_index == 0) 438 MEP_OMASK = optbits; 439 else 440 MEP_OMASK = (MEP_OMASK & ~optbitset) | optbits; 441 442 /* Set the machine number and endian. */ 443 gas_cgen_cpu_desc = mep_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0, 444 CGEN_CPU_OPEN_ENDIAN, 445 target_big_endian 446 ? CGEN_ENDIAN_BIG 447 : CGEN_ENDIAN_LITTLE, 448 CGEN_CPU_OPEN_ISAS, 0, 449 CGEN_CPU_OPEN_END); 450 mep_cgen_init_asm (gas_cgen_cpu_desc); 451 452 /* This is a callback from cgen to gas to parse operands. */ 453 cgen_set_parse_operand_fn (gas_cgen_cpu_desc, mep_parse_operand); 454 455 /* Identify the architecture. */ 456 bfd_default_set_arch_mach (stdoutput, bfd_arch_mep, mep_machine ()); 457 458 /* Store the configuration number and core. */ 459 bfd_set_private_flags (stdoutput, MEP_CPU | MEP_CONFIG | library_flag); 460 461 /* Initialize the array we'll be using to store fixups. */ 462 gas_cgen_initialize_saved_fixups_array(); 463} 464 465/* Variant of mep_cgen_assemble_insn. Assemble insn STR of cpu CD as a 466 coprocessor instruction, if possible, into FIELDS, BUF, and INSN. */ 467 468static const CGEN_INSN * 469mep_cgen_assemble_cop_insn (CGEN_CPU_DESC cd, 470 const char *str, 471 CGEN_FIELDS *fields, 472 CGEN_INSN_BYTES_PTR buf, 473 const struct cgen_insn *pinsn) 474{ 475 const char *start; 476 CGEN_INSN_LIST *ilist; 477 const char *errmsg = NULL; 478 479 /* The instructions are stored in hashed lists. */ 480 ilist = CGEN_ASM_LOOKUP_INSN (gas_cgen_cpu_desc, 481 CGEN_INSN_MNEMONIC (pinsn)); 482 483 start = str; 484 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist)) 485 { 486 const CGEN_INSN *insn = ilist->insn; 487 if (strcmp (CGEN_INSN_MNEMONIC (ilist->insn), 488 CGEN_INSN_MNEMONIC (pinsn)) == 0 489 && MEP_INSN_COP_P (ilist->insn) 490 && mep_cgen_insn_supported (cd, insn)) 491 { 492 str = start; 493 494 /* skip this insn if str doesn't look right lexically */ 495 if (CGEN_INSN_RX (insn) != NULL && 496 regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH) 497 continue; 498 499 /* Allow parse/insert handlers to obtain length of insn. */ 500 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); 501 502 errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields); 503 if (errmsg != NULL) 504 continue; 505 506 errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf, 507 (bfd_vma) 0); 508 if (errmsg != NULL) 509 continue; 510 511 return insn; 512 } 513 } 514 return pinsn; 515} 516 517static void 518mep_save_insn (mep_insn insn) 519{ 520 /* Consider change MAX_SAVED_FIXUP_CHAINS to MAX_PARALLEL_INSNS. */ 521 if (num_insns_saved < 0 || num_insns_saved >= MAX_SAVED_FIXUP_CHAINS) 522 { 523 as_fatal("index into saved_insns[] out of bounds."); 524 return; 525 } 526 saved_insns[num_insns_saved] = insn; 527 gas_cgen_save_fixups(num_insns_saved); 528 num_insns_saved++; 529} 530 531static void 532mep_check_parallel32_scheduling (void) 533{ 534 int insn0iscopro, insn1iscopro, insn0length, insn1length; 535 536 /* More than two instructions means that either someone is referring to 537 an internally parallel core or an internally parallel coprocessor, 538 neither of which are supported at this time. */ 539 if ( num_insns_saved > 2 ) 540 as_fatal("Internally paralled cores and coprocessors not supported."); 541 542 /* If there are no insns saved, that's ok. Just return. This will 543 happen when mep_process_saved_insns is called when the end of the 544 source file is reached and there are no insns left to be processed. */ 545 if (num_insns_saved == 0) 546 return; 547 548 /* Check some of the attributes of the first insn. */ 549 insn0iscopro = MEP_INSN_COP_P (saved_insns[0].insn); 550 insn0length = CGEN_FIELDS_BITSIZE (& saved_insns[0].fields); 551 552 if (num_insns_saved == 2) 553 { 554 /* Check some of the attributes of the first insn. */ 555 insn1iscopro = MEP_INSN_COP_P (saved_insns[1].insn); 556 insn1length = CGEN_FIELDS_BITSIZE (& saved_insns[1].fields); 557 558 if ((insn0iscopro && !insn1iscopro) 559 || (insn1iscopro && !insn0iscopro)) 560 { 561 /* We have one core and one copro insn. If their sizes 562 add up to 32, then the combination is valid. */ 563 if (insn0length + insn1length == 32) 564 return; 565 else 566 as_bad ("core and copro insn lengths must total 32 bits."); 567 } 568 else 569 as_bad ("vliw group must consist of 1 core and 1 copro insn."); 570 } 571 else 572 { 573 /* If we arrive here, we have one saved instruction. There are a 574 number of possible cases: 575 576 1. The instruction is a 32 bit core or coprocessor insn and 577 can be executed by itself. Valid. 578 579 2. The instrucion is a core instruction for which a cop nop 580 exists. In this case, insert the cop nop into the saved 581 insn array after the core insn and return. Valid. 582 583 3. The instruction is a coprocessor insn for which a core nop 584 exists. In this case, move the coprocessor insn to the 585 second element of the array and put the nop in the first 586 element then return. Valid. 587 588 4. The instruction is a core or coprocessor instruction for 589 which there is no matching coprocessor or core nop to use 590 to form a valid vliw insn combination. In this case, we 591 we have to abort. */ 592 593 if (insn0length > 32) 594 as_fatal ("Cannot use 48- or 64-bit insns with a 32 bit datapath."); 595 596 if (insn0length == 32) 597 return; 598 599 /* Insn is smaller than datapath. If there are no matching 600 nops for this insn, then terminate assembly. */ 601 if (CGEN_INSN_ATTR_VALUE (saved_insns[0].insn, 602 CGEN_INSN_VLIW32_NO_MATCHING_NOP)) 603 as_fatal ("No valid nop."); 604 605 /* At this point we know that we have a single 16-bit insn that has 606 a matching nop. We have to assemble it and put it into the saved 607 insn and fixup chain arrays. */ 608 609 if (insn0iscopro) 610 { 611 char *errmsg; 612 mep_insn insn; 613 614 /* Move the insn and it's fixups to the second element of the 615 saved insns arrary and insert a 16 bit core nope into the 616 first element. */ 617 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "nop", 618 &insn.fields, insn.buffer, 619 &errmsg); 620 if (!insn.insn) 621 { 622 as_bad ("%s", errmsg); 623 return; 624 } 625 626 /* Move the insn in element 0 to element 1 and insert the 627 nop into element 0. Move the fixups in element 0 to 628 element 1 and save the current fixups to element 0. 629 Really there aren't any fixups at this point because we're 630 inserting a nop but we might as well be general so that 631 if there's ever a need to insert a general insn, we'll 632 have an example. */ 633 saved_insns[1] = saved_insns[0]; 634 saved_insns[0] = insn; 635 num_insns_saved++; 636 gas_cgen_swap_fixups (0); 637 gas_cgen_save_fixups (1); 638 } 639 else 640 { 641 char * errmsg; 642 mep_insn insn; 643 int insn_num = saved_insns[0].insn->base->num; 644 645 /* Use 32 bit branches and skip the nop. */ 646 if (insn_num == MEP_INSN_BSR12 647 || insn_num == MEP_INSN_BEQZ 648 || insn_num == MEP_INSN_BNEZ) 649 return; 650 651 /* Insert a 16-bit coprocessor nop. Note that at the time */ 652 /* this was done, no 16-bit coprocessor nop was defined. */ 653 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop16", 654 &insn.fields, insn.buffer, 655 &errmsg); 656 if (!insn.insn) 657 { 658 as_bad ("%s", errmsg); 659 return; 660 } 661 662 /* Now put the insn and fixups into the arrays. */ 663 mep_save_insn (insn); 664 } 665 } 666} 667 668static void 669mep_check_parallel64_scheduling (void) 670{ 671 int insn0iscopro, insn1iscopro, insn0length, insn1length; 672 673 /* More than two instructions means that someone is referring to an 674 internally parallel core or an internally parallel coprocessor. */ 675 /* These are not currently supported. */ 676 if (num_insns_saved > 2) 677 as_fatal ("Internally parallel cores of coprocessors not supported."); 678 679 /* If there are no insns saved, that's ok. Just return. This will 680 happen when mep_process_saved_insns is called when the end of the 681 source file is reached and there are no insns left to be processed. */ 682 if (num_insns_saved == 0) 683 return; 684 685 /* Check some of the attributes of the first insn. */ 686 insn0iscopro = MEP_INSN_COP_P (saved_insns[0].insn); 687 insn0length = CGEN_FIELDS_BITSIZE (& saved_insns[0].fields); 688 689 if (num_insns_saved == 2) 690 { 691 /* Check some of the attributes of the first insn. */ 692 insn1iscopro = MEP_INSN_COP_P (saved_insns[1].insn); 693 insn1length = CGEN_FIELDS_BITSIZE (& saved_insns[1].fields); 694 695 if ((insn0iscopro && !insn1iscopro) 696 || (insn1iscopro && !insn0iscopro)) 697 { 698 /* We have one core and one copro insn. If their sizes 699 add up to 64, then the combination is valid. */ 700 if (insn0length + insn1length == 64) 701 return; 702 else 703 as_bad ("core and copro insn lengths must total 64 bits."); 704 } 705 else 706 as_bad ("vliw group must consist of 1 core and 1 copro insn."); 707 } 708 else 709 { 710 /* If we arrive here, we have one saved instruction. There are a 711 number of possible cases: 712 713 1. The instruction is a 64 bit coprocessor insn and can be 714 executed by itself. Valid. 715 716 2. The instrucion is a core instruction for which a cop nop 717 exists. In this case, insert the cop nop into the saved 718 insn array after the core insn and return. Valid. 719 720 3. The instruction is a coprocessor insn for which a core nop 721 exists. In this case, move the coprocessor insn to the 722 second element of the array and put the nop in the first 723 element then return. Valid. 724 725 4. The instruction is a core or coprocessor instruction for 726 which there is no matching coprocessor or core nop to use 727 to form a valid vliw insn combination. In this case, we 728 we have to abort. */ 729 730 /* If the insn is 64 bits long, it can run alone. The size check 731 is done indepependantly of whether the insn is core or copro 732 in case 64 bit coprocessor insns are added later. */ 733 if (insn0length == 64) 734 return; 735 736 /* Insn is smaller than datapath. If there are no matching 737 nops for this insn, then terminate assembly. */ 738 if (CGEN_INSN_ATTR_VALUE (saved_insns[0].insn, 739 CGEN_INSN_VLIW64_NO_MATCHING_NOP)) 740 as_fatal ("No valid nop."); 741 742 if (insn0iscopro) 743 { 744 char *errmsg; 745 mep_insn insn; 746 int i; 747 748 /* Initialize the insn buffer. */ 749 for (i = 0; i < 64; i++) 750 insn.buffer[i] = '\0'; 751 752 /* We have a coprocessor insn. At this point in time there 753 are is 32-bit core nop. There is only a 16-bit core 754 nop. The idea is to allow for a relatively arbitrary 755 coprocessor to be specified. We aren't looking at 756 trying to cover future changes in the core at this time 757 since it is assumed that the core will remain fairly 758 static. If there ever are 32 or 48 bit core nops added, 759 they will require entries below. */ 760 761 if (insn0length == 48) 762 { 763 /* Move the insn and fixups to the second element of the 764 arrays then assemble and insert a 16 bit core nop. */ 765 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "nop", 766 & insn.fields, insn.buffer, 767 & errmsg); 768 } 769 else 770 { 771 /* If this is reached, then we have a single coprocessor 772 insn that is not 48 bits long, but for which the assembler 773 thinks there is a matching core nop. If a 32-bit core 774 nop has been added, then make the necessary changes and 775 handle its assembly and insertion here. Otherwise, 776 go figure out why either: 777 778 1. The assembler thinks that there is a 32-bit core nop 779 to match a 32-bit coprocessor insn, or 780 2. The assembler thinks that there is a 48-bit core nop 781 to match a 16-bit coprocessor insn. */ 782 783 as_fatal ("Assembler expects a non-existent core nop."); 784 } 785 786 if (!insn.insn) 787 { 788 as_bad ("%s", errmsg); 789 return; 790 } 791 792 /* Move the insn in element 0 to element 1 and insert the 793 nop into element 0. Move the fixups in element 0 to 794 element 1 and save the current fixups to element 0. 795 Really there aren't any fixups at this point because we're 796 inserting a nop but we might as well be general so that 797 if there's ever a need to insert a general insn, we'll 798 have an example. */ 799 800 saved_insns[1] = saved_insns[0]; 801 saved_insns[0] = insn; 802 num_insns_saved++; 803 gas_cgen_swap_fixups(0); 804 gas_cgen_save_fixups(1); 805 806 } 807 else 808 { 809 char * errmsg; 810 mep_insn insn; 811 int i; 812 813 /* Initialize the insn buffer */ 814 for (i = 0; i < 64; i++) 815 insn.buffer[i] = '\0'; 816 817 /* We have a core insn. We have to handle all possible nop 818 lengths. If a coprocessor doesn't have a nop of a certain 819 length but there exists core insns that when combined with 820 a nop of that length would fill the datapath, those core 821 insns will be flagged with the VLIW_NO_CORRESPONDING_NOP 822 attribute. That will ensure that when used in a way that 823 requires a nop to be inserted, assembly will terminate 824 before reaching this section of code. This guarantees 825 that cases below which would result in the attempted 826 insertion of nop that doesn't exist will never be entered. */ 827 if (insn0length == 16) 828 { 829 /* Insert 48 bit coprocessor nop. */ 830 /* Assemble it and put it into the arrays. */ 831 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop48", 832 &insn.fields, insn.buffer, 833 &errmsg); 834 } 835 else if (insn0length == 32) 836 { 837 /* Insert 32 bit coprocessor nop. */ 838 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop32", 839 &insn.fields, insn.buffer, 840 &errmsg); 841 } 842 else if (insn0length == 48) 843 { 844 /* Insert 16 bit coprocessor nop. */ 845 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop16", 846 &insn.fields, insn.buffer, 847 &errmsg); 848 } 849 else 850 /* Core insn has an invalid length. Something has gone wrong. */ 851 as_fatal ("Core insn has invalid length! Something is wrong!"); 852 853 if (!insn.insn) 854 { 855 as_bad ("%s", errmsg); 856 return; 857 } 858 859 /* Now put the insn and fixups into the arrays. */ 860 mep_save_insn (insn); 861 } 862 } 863} 864 865/* The scheduling functions are just filters for invalid combinations. 866 If there is a violation, they terminate assembly. Otherise they 867 just fall through. Succesful combinations cause no side effects 868 other than valid nop insertion. */ 869 870static void 871mep_check_parallel_scheduling (void) 872{ 873 /* This is where we will eventually read the config information 874 and choose which scheduling checking function to call. */ 875 if (MEP_VLIW64) 876 mep_check_parallel64_scheduling (); 877 else 878 mep_check_parallel32_scheduling (); 879} 880 881static void 882mep_process_saved_insns (void) 883{ 884 int i; 885 886 gas_cgen_save_fixups (MAX_SAVED_FIXUP_CHAINS - 1); 887 888 /* We have to check for valid scheduling here. */ 889 mep_check_parallel_scheduling (); 890 891 /* If the last call didn't cause assembly to terminate, we have 892 a valid vliw insn/insn pair saved. Restore this instructions' 893 fixups and process the insns. */ 894 for (i = 0;i<num_insns_saved;i++) 895 { 896 gas_cgen_restore_fixups (i); 897 gas_cgen_finish_insn (saved_insns[i].insn, saved_insns[i].buffer, 898 CGEN_FIELDS_BITSIZE (& saved_insns[i].fields), 899 1, NULL); 900 } 901 gas_cgen_restore_fixups (MAX_SAVED_FIXUP_CHAINS - 1); 902 903 /* Clear the fixups and reset the number insn saved to 0. */ 904 gas_cgen_initialize_saved_fixups_array (); 905 num_insns_saved = 0; 906 listing_prev_line (); 907} 908 909void 910md_assemble (char * str) 911{ 912 static CGEN_BITSET* isas = NULL; 913 char * errmsg; 914 915 /* Initialize GAS's cgen interface for a new instruction. */ 916 gas_cgen_init_parse (); 917 918 /* There are two possible modes: core and vliw. We have to assemble 919 differently for each. 920 921 Core Mode: We assemble normally. All instructions are on a 922 single line and are made up of one mnemonic and one 923 set of operands. 924 VLIW Mode: Vliw combinations are indicated as follows: 925 926 core insn 927 + copro insn 928 929 We want to handle the general case where more than 930 one instruction can be preceeded by a +. This will 931 happen later if we add support for internally parallel 932 coprocessors. We'll make the parsing nice and general 933 so that it can handle an arbitrary number of insns 934 with leading +'s. The actual checking for valid 935 combinations is done elsewhere. */ 936 937 /* Initialize the isa to refer to the core. */ 938 if (isas == NULL) 939 isas = cgen_bitset_copy (& MEP_CORE_ISA); 940 else 941 { 942 cgen_bitset_clear (isas); 943 cgen_bitset_union (isas, & MEP_CORE_ISA, isas); 944 } 945 gas_cgen_cpu_desc->isas = isas; 946 947 if (mode == VLIW) 948 { 949 /* VLIW mode. */ 950 951 int thisInsnIsCopro = 0; 952 mep_insn insn; 953 int i; 954 955 /* Initialize the insn buffer */ 956 957 if (! CGEN_INT_INSN_P) 958 for (i=0; i < CGEN_MAX_INSN_SIZE; i++) 959 insn.buffer[i]='\0'; 960 961 /* Can't tell core / copro insns apart at parse time! */ 962 cgen_bitset_union (isas, & MEP_COP_ISA, isas); 963 964 /* Assemble the insn so we can examine its attributes. */ 965 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, str, 966 &insn.fields, insn.buffer, 967 &errmsg); 968 if (!insn.insn) 969 { 970 as_bad ("%s", errmsg); 971 return; 972 } 973 mep_check_for_disabled_registers (&insn); 974 975 /* Check to see if it's a coprocessor instruction. */ 976 thisInsnIsCopro = MEP_INSN_COP_P (insn.insn); 977 978 if (!thisInsnIsCopro) 979 { 980 insn.insn = mep_cgen_assemble_cop_insn (gas_cgen_cpu_desc, str, 981 &insn.fields, insn.buffer, 982 insn.insn); 983 thisInsnIsCopro = MEP_INSN_COP_P (insn.insn); 984 mep_check_for_disabled_registers (&insn); 985 } 986 987 if (pluspresent) 988 { 989 /* A plus was present. */ 990 /* Check for a + with a core insn and abort if found. */ 991 if (!thisInsnIsCopro) 992 { 993 as_fatal("A core insn cannot be preceeded by a +.\n"); 994 return; 995 } 996 997 if (num_insns_saved > 0) 998 { 999 /* There are insns in the queue. Add this one. */ 1000 mep_save_insn (insn); 1001 } 1002 else 1003 { 1004 /* There are no insns in the queue and a plus is present. 1005 This is a syntax error. Let's not tolerate this. 1006 We can relax this later if necessary. */ 1007 as_bad (_("Invalid use of parallelization operator.")); 1008 return; 1009 } 1010 } 1011 else 1012 { 1013 /* No plus was present. */ 1014 if (num_insns_saved > 0) 1015 { 1016 /* There are insns saved and we came across an insn without a 1017 leading +. That's the signal to process the saved insns 1018 before proceeding then treat the current insn as the first 1019 in a new vliw group. */ 1020 mep_process_saved_insns (); 1021 num_insns_saved = 0; 1022 /* mep_save_insn (insn); */ 1023 } 1024 mep_save_insn (insn); 1025#if 0 1026 else 1027 { 1028 1029 /* Core Insn. Add it to the beginning of the queue. */ 1030 mep_save_insn (insn); 1031 /* gas_cgen_save_fixups(num_insns_saved); */ 1032 } 1033#endif 1034 } 1035 1036 pluspresent = 0; 1037 } 1038 else 1039 { 1040 /* Core mode. */ 1041 1042 /* Only single instructions are assembled in core mode. */ 1043 mep_insn insn; 1044 1045 /* If a leading '+' was present, issue an error. 1046 That's not allowed in core mode. */ 1047 if (pluspresent) 1048 { 1049 as_bad (_("Leading plus sign not allowed in core mode")); 1050 return; 1051 } 1052 1053 insn.insn = mep_cgen_assemble_insn 1054 (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg); 1055 1056 if (!insn.insn) 1057 { 1058 as_bad ("%s", errmsg); 1059 return; 1060 } 1061 gas_cgen_finish_insn (insn.insn, insn.buffer, 1062 CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL); 1063 mep_check_for_disabled_registers (&insn); 1064 } 1065} 1066 1067valueT 1068md_section_align (segT segment, valueT size) 1069{ 1070 int align = bfd_get_section_alignment (stdoutput, segment); 1071 return ((size + (1 << align) - 1) & (-1 << align)); 1072} 1073 1074 1075symbolS * 1076md_undefined_symbol (char *name ATTRIBUTE_UNUSED) 1077{ 1078 return 0; 1079} 1080 1081/* Interface to relax_segment. */ 1082 1083 1084const relax_typeS md_relax_table[] = 1085{ 1086 /* The fields are: 1087 1) most positive reach of this state, 1088 2) most negative reach of this state, 1089 3) how many bytes this mode will have in the variable part of the frag 1090 4) which index into the table to try if we can't fit into this one. */ 1091 /* Note that we use "beq" because "jmp" has a peculiarity - it cannot 1092 jump to addresses with any bits 27..24 set. So, we use beq as a 1093 17-bit pc-relative branch to avoid using jmp, just in case. */ 1094 1095 /* 0 */ { 0, 0, 0, 0 }, /* unused */ 1096 /* 1 */ { 0, 0, 0, 0 }, /* marker for "don't know yet" */ 1097 1098 /* 2 */ { 2047, -2048, 0, 3 }, /* bsr12 */ 1099 /* 3 */ { 0, 0, 2, 0 }, /* bsr16 */ 1100 1101 /* 4 */ { 2047, -2048, 0, 5 }, /* bra */ 1102 /* 5 */ { 65535, -65536, 2, 6 }, /* beq $0,$0 */ 1103 /* 6 */ { 0, 0, 2, 0 }, /* jmp24 */ 1104 1105 /* 7 */ { 65535, -65536, 0, 8 }, /* beqi */ 1106 /* 8 */ { 0, 0, 4, 0 }, /* bnei/jmp */ 1107 1108 /* 9 */ { 127, -128, 0, 10 }, /* beqz */ 1109 /* 10 */ { 65535, -65536, 2, 11 }, /* beqi */ 1110 /* 11 */ { 0, 0, 4, 0 }, /* bnei/jmp */ 1111 1112 /* 12 */ { 65535, -65536, 0, 13 }, /* bnei */ 1113 /* 13 */ { 0, 0, 4, 0 }, /* beqi/jmp */ 1114 1115 /* 14 */ { 127, -128, 0, 15 }, /* bnez */ 1116 /* 15 */ { 65535, -65536, 2, 16 }, /* bnei */ 1117 /* 16 */ { 0, 0, 4, 0 }, /* beqi/jmp */ 1118 1119 /* 17 */ { 65535, -65536, 0, 13 }, /* bgei */ 1120 /* 18 */ { 0, 0, 4, 0 }, 1121 /* 19 */ { 65535, -65536, 0, 13 }, /* blti */ 1122 /* 20 */ { 0, 0, 4, 0 }, 1123 /* 19 */ { 65535, -65536, 0, 13 }, /* bcpeq */ 1124 /* 20 */ { 0, 0, 4, 0 }, 1125 /* 19 */ { 65535, -65536, 0, 13 }, /* bcpne */ 1126 /* 20 */ { 0, 0, 4, 0 }, 1127 /* 19 */ { 65535, -65536, 0, 13 }, /* bcpat */ 1128 /* 20 */ { 0, 0, 4, 0 }, 1129 /* 19 */ { 65535, -65536, 0, 13 }, /* bcpaf */ 1130 /* 20 */ { 0, 0, 4, 0 } 1131}; 1132 1133/* Pseudo-values for 64 bit "insns" which are combinations of two 32 1134 bit insns. */ 1135typedef enum { 1136 MEP_PSEUDO64_NONE, 1137 MEP_PSEUDO64_16BITCC, 1138 MEP_PSEUDO64_32BITCC, 1139} MepPseudo64Values; 1140 1141static struct { 1142 int insn; 1143 int growth; 1144 int insn_for_extern; 1145} subtype_mappings[] = { 1146 { 0, 0, 0 }, 1147 { 0, 0, 0 }, 1148 { MEP_INSN_BSR12, 0, MEP_INSN_BSR24 }, 1149 { MEP_INSN_BSR24, 2, MEP_INSN_BSR24 }, 1150 { MEP_INSN_BRA, 0, MEP_INSN_BRA }, 1151 { MEP_INSN_BEQ, 2, MEP_INSN_BEQ }, 1152 { MEP_INSN_JMP, 2, MEP_INSN_JMP }, 1153 { MEP_INSN_BEQI, 0, MEP_INSN_BEQI }, 1154 { -1, 4, MEP_PSEUDO64_32BITCC }, 1155 { MEP_INSN_BEQZ, 0, MEP_INSN_BEQZ }, 1156 { MEP_INSN_BEQI, 2, MEP_INSN_BEQI }, 1157 { -1, 4, MEP_PSEUDO64_16BITCC }, 1158 { MEP_INSN_BNEI, 0, MEP_INSN_BNEI }, 1159 { -1, 4, MEP_PSEUDO64_32BITCC }, 1160 { MEP_INSN_BNEZ, 0, MEP_INSN_BNEZ }, 1161 { MEP_INSN_BNEI, 2, MEP_INSN_BNEI }, 1162 { -1, 4, MEP_PSEUDO64_16BITCC }, 1163 { MEP_INSN_BGEI, 0, MEP_INSN_BGEI }, 1164 { -1, 4, MEP_PSEUDO64_32BITCC }, 1165 { MEP_INSN_BLTI, 0, MEP_INSN_BLTI }, 1166 { -1, 4, MEP_PSEUDO64_32BITCC }, 1167 { MEP_INSN_BCPEQ, 0, MEP_INSN_BCPEQ }, 1168 { -1, 4, MEP_PSEUDO64_32BITCC }, 1169 { MEP_INSN_BCPNE, 0, MEP_INSN_BCPNE }, 1170 { -1, 4, MEP_PSEUDO64_32BITCC }, 1171 { MEP_INSN_BCPAT, 0, MEP_INSN_BCPAT }, 1172 { -1, 4, MEP_PSEUDO64_32BITCC }, 1173 { MEP_INSN_BCPAF, 0, MEP_INSN_BCPAF }, 1174 { -1, 4, MEP_PSEUDO64_32BITCC } 1175}; 1176#define NUM_MAPPINGS (sizeof (subtype_mappings) / sizeof (subtype_mappings[0])) 1177 1178void 1179mep_prepare_relax_scan (fragS *fragP, offsetT *aim, relax_substateT this_state) 1180{ 1181 symbolS *symbolP = fragP->fr_symbol; 1182 if (symbolP && !S_IS_DEFINED (symbolP)) 1183 *aim = 0; 1184 /* Adjust for MeP pcrel not being relative to the next opcode. */ 1185 *aim += 2 + md_relax_table[this_state].rlx_length; 1186} 1187 1188static int 1189insn_to_subtype (int insn) 1190{ 1191 unsigned int i; 1192 for (i=0; i<NUM_MAPPINGS; i++) 1193 if (insn == subtype_mappings[i].insn) 1194 return i; 1195 abort (); 1196} 1197 1198/* Return an initial guess of the length by which a fragment must grow 1199 to hold a branch to reach its destination. Also updates fr_type 1200 and fr_subtype as necessary. 1201 1202 Called just before doing relaxation. Any symbol that is now 1203 undefined will not become defined. The guess for fr_var is 1204 ACTUALLY the growth beyond fr_fix. Whatever we do to grow fr_fix 1205 or fr_var contributes to our returned value. Although it may not 1206 be explicit in the frag, pretend fr_var starts with a 0 value. */ 1207 1208int 1209md_estimate_size_before_relax (fragS * fragP, segT segment) 1210{ 1211 if (fragP->fr_subtype == 1) 1212 fragP->fr_subtype = insn_to_subtype (fragP->fr_cgen.insn->base->num); 1213 1214 if (S_GET_SEGMENT (fragP->fr_symbol) != segment) 1215 { 1216 int new_insn; 1217 1218 new_insn = subtype_mappings[fragP->fr_subtype].insn_for_extern; 1219 fragP->fr_subtype = insn_to_subtype (new_insn); 1220 } 1221 1222 if (MEP_VLIW && ! MEP_VLIW64 1223 && (bfd_get_section_flags (stdoutput, segment) & SEC_MEP_VLIW)) 1224 { 1225 /* Use 32 bit branches for vliw32 so the vliw word is not split. */ 1226 switch (fragP->fr_cgen.insn->base->num) 1227 { 1228 case MEP_INSN_BSR12: 1229 fragP->fr_subtype = insn_to_subtype 1230 (subtype_mappings[fragP->fr_subtype].insn_for_extern); 1231 break; 1232 case MEP_INSN_BEQZ: 1233 fragP->fr_subtype ++; 1234 break; 1235 case MEP_INSN_BNEZ: 1236 fragP->fr_subtype ++; 1237 break; 1238 } 1239 } 1240 1241 if (fragP->fr_cgen.insn->base 1242 && fragP->fr_cgen.insn->base->num 1243 != subtype_mappings[fragP->fr_subtype].insn) 1244 { 1245 int new_insn= subtype_mappings[fragP->fr_subtype].insn; 1246 if (new_insn != -1) 1247 { 1248 fragP->fr_cgen.insn = (fragP->fr_cgen.insn 1249 - fragP->fr_cgen.insn->base->num 1250 + new_insn); 1251 } 1252 } 1253 1254 return subtype_mappings[fragP->fr_subtype].growth; 1255} 1256 1257/* *fragP has been relaxed to its final size, and now needs to have 1258 the bytes inside it modified to conform to the new size. 1259 1260 Called after relaxation is finished. 1261 fragP->fr_type == rs_machine_dependent. 1262 fragP->fr_subtype is the subtype of what the address relaxed to. */ 1263 1264static int 1265target_address_for (fragS *frag) 1266{ 1267 int rv = frag->fr_offset; 1268 symbolS *sym = frag->fr_symbol; 1269 1270 if (sym) 1271 rv += S_GET_VALUE (sym); 1272 1273 return rv; 1274} 1275 1276void 1277md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, 1278 segT sec ATTRIBUTE_UNUSED, 1279 fragS *fragP) 1280{ 1281 int addend, rn, bit = 0; 1282 int operand; 1283 int where = fragP->fr_opcode - fragP->fr_literal; 1284 int e = target_big_endian ? 0 : 1; 1285 1286 addend = target_address_for (fragP) - (fragP->fr_address + where); 1287 1288 if (subtype_mappings[fragP->fr_subtype].insn == -1) 1289 { 1290 fragP->fr_fix += subtype_mappings[fragP->fr_subtype].growth; 1291 switch (subtype_mappings[fragP->fr_subtype].insn_for_extern) 1292 { 1293 case MEP_PSEUDO64_16BITCC: 1294 fragP->fr_opcode[1^e] = ((fragP->fr_opcode[1^e] & 1) ^ 1) | 0x06; 1295 fragP->fr_opcode[2^e] = 0xd8; 1296 fragP->fr_opcode[3^e] = 0x08; 1297 fragP->fr_opcode[4^e] = 0; 1298 fragP->fr_opcode[5^e] = 0; 1299 where += 2; 1300 break; 1301 case MEP_PSEUDO64_32BITCC: 1302 if (fragP->fr_opcode[0^e] & 0x10) 1303 fragP->fr_opcode[1^e] ^= 0x01; 1304 else 1305 fragP->fr_opcode[1^e] ^= 0x04; 1306 fragP->fr_opcode[2^e] = 0; 1307 fragP->fr_opcode[3^e] = 4; 1308 fragP->fr_opcode[4^e] = 0xd8; 1309 fragP->fr_opcode[5^e] = 0x08; 1310 fragP->fr_opcode[6^e] = 0; 1311 fragP->fr_opcode[7^e] = 0; 1312 where += 4; 1313 break; 1314 default: 1315 abort (); 1316 } 1317 fragP->fr_cgen.insn = (fragP->fr_cgen.insn 1318 - fragP->fr_cgen.insn->base->num 1319 + MEP_INSN_JMP); 1320 operand = MEP_OPERAND_PCABS24A2; 1321 } 1322 else 1323 switch (fragP->fr_cgen.insn->base->num) 1324 { 1325 case MEP_INSN_BSR12: 1326 fragP->fr_opcode[0^e] = 0xb0 | ((addend >> 8) & 0x0f); 1327 fragP->fr_opcode[1^e] = 0x01 | (addend & 0xfe); 1328 operand = MEP_OPERAND_PCREL12A2; 1329 break; 1330 1331 case MEP_INSN_BSR24: 1332 fragP->fr_fix += 2; 1333 fragP->fr_opcode[0^e] = 0xd8 | ((addend >> 5) & 0x07); 1334 fragP->fr_opcode[1^e] = 0x09 | ((addend << 3) & 0xf0); 1335 fragP->fr_opcode[2^e] = 0x00 | ((addend >>16) & 0xff); 1336 fragP->fr_opcode[3^e] = 0x00 | ((addend >> 8) & 0xff); 1337 operand = MEP_OPERAND_PCREL24A2; 1338 break; 1339 1340 case MEP_INSN_BRA: 1341 fragP->fr_opcode[0^e] = 0xb0 | ((addend >> 8) & 0x0f); 1342 fragP->fr_opcode[1^e] = 0x00 | (addend & 0xfe); 1343 operand = MEP_OPERAND_PCREL12A2; 1344 break; 1345 1346 case MEP_INSN_BEQ: 1347 /* The default relax_frag doesn't change the state if there is no 1348 growth, so we must manually handle converting out-of-range BEQ 1349 instructions to JMP. */ 1350 if (addend <= 65535 && addend >= -65536) 1351 { 1352 fragP->fr_fix += 2; 1353 fragP->fr_opcode[0^e] = 0xe0; 1354 fragP->fr_opcode[1^e] = 0x01; 1355 fragP->fr_opcode[2^e] = 0x00 | ((addend >> 9) & 0xff); 1356 fragP->fr_opcode[3^e] = 0x00 | ((addend >> 1) & 0xff); 1357 operand = MEP_OPERAND_PCREL17A2; 1358 break; 1359 } 1360 /* ...FALLTHROUGH... */ 1361 1362 case MEP_INSN_JMP: 1363 addend = target_address_for (fragP); 1364 fragP->fr_fix += 2; 1365 fragP->fr_opcode[0^e] = 0xd8 | ((addend >> 5) & 0x07); 1366 fragP->fr_opcode[1^e] = 0x08 | ((addend << 3) & 0xf0); 1367 fragP->fr_opcode[2^e] = 0x00 | ((addend >>16) & 0xff); 1368 fragP->fr_opcode[3^e] = 0x00 | ((addend >> 8) & 0xff); 1369 operand = MEP_OPERAND_PCABS24A2; 1370 break; 1371 1372 case MEP_INSN_BNEZ: 1373 bit = 1; 1374 case MEP_INSN_BEQZ: 1375 fragP->fr_opcode[1^e] = bit | (addend & 0xfe); 1376 operand = MEP_OPERAND_PCREL8A2; 1377 break; 1378 1379 case MEP_INSN_BNEI: 1380 bit = 4; 1381 case MEP_INSN_BEQI: 1382 if (subtype_mappings[fragP->fr_subtype].growth) 1383 { 1384 fragP->fr_fix += subtype_mappings[fragP->fr_subtype].growth; 1385 rn = fragP->fr_opcode[0^e] & 0x0f; 1386 fragP->fr_opcode[0^e] = 0xe0 | rn; 1387 fragP->fr_opcode[1^e] = bit; 1388 } 1389 fragP->fr_opcode[2^e] = 0x00 | ((addend >> 9) & 0xff); 1390 fragP->fr_opcode[3^e] = 0x00 | ((addend >> 1) & 0xff); 1391 operand = MEP_OPERAND_PCREL17A2; 1392 break; 1393 1394 case MEP_INSN_BLTI: 1395 case MEP_INSN_BGEI: 1396 case MEP_INSN_BCPEQ: 1397 case MEP_INSN_BCPNE: 1398 case MEP_INSN_BCPAT: 1399 case MEP_INSN_BCPAF: 1400 /* No opcode change needed, just operand. */ 1401 fragP->fr_opcode[2^e] = (addend >> 9) & 0xff; 1402 fragP->fr_opcode[3^e] = (addend >> 1) & 0xff; 1403 operand = MEP_OPERAND_PCREL17A2; 1404 break; 1405 1406 default: 1407 abort (); 1408 } 1409 1410 if (S_GET_SEGMENT (fragP->fr_symbol) != sec 1411 || operand == MEP_OPERAND_PCABS24A2) 1412 { 1413 assert (fragP->fr_cgen.insn != 0); 1414 gas_cgen_record_fixup (fragP, 1415 where, 1416 fragP->fr_cgen.insn, 1417 (fragP->fr_fix - where) * 8, 1418 cgen_operand_lookup_by_num (gas_cgen_cpu_desc, 1419 operand), 1420 fragP->fr_cgen.opinfo, 1421 fragP->fr_symbol, fragP->fr_offset); 1422 } 1423} 1424 1425 1426/* Functions concerning relocs. */ 1427 1428void 1429mep_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) 1430{ 1431 /* If we already know the fixup value, adjust it in the same 1432 way that the linker would have done. */ 1433 if (fixP->fx_addsy == 0) 1434 switch (fixP->fx_cgen.opinfo) 1435 { 1436 case BFD_RELOC_MEP_LOW16: 1437 *valP = ((long)(*valP & 0xffff)) << 16 >> 16; 1438 break; 1439 case BFD_RELOC_MEP_HI16U: 1440 *valP >>= 16; 1441 break; 1442 case BFD_RELOC_MEP_HI16S: 1443 *valP = (*valP + 0x8000) >> 16; 1444 break; 1445 } 1446 1447 /* Now call cgen's md_aply_fix. */ 1448 gas_cgen_md_apply_fix (fixP, valP, seg); 1449} 1450 1451long 1452md_pcrel_from_section (fixS *fixP, segT sec) 1453{ 1454 if (fixP->fx_addsy != (symbolS *) NULL 1455 && (! S_IS_DEFINED (fixP->fx_addsy) 1456 || S_GET_SEGMENT (fixP->fx_addsy) != sec)) 1457 /* The symbol is undefined (or is defined but not in this section). 1458 Let the linker figure it out. */ 1459 return 0; 1460 1461 /* Return the address of the opcode - cgen adjusts for opcode size 1462 itself, to be consistent with the disassembler, which must do 1463 so. */ 1464 return fixP->fx_where + fixP->fx_frag->fr_address; 1465} 1466 1467/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP. 1468 Returns BFD_RELOC_NONE if no reloc type can be found. 1469 *FIXP may be modified if desired. */ 1470 1471#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE) 1472#define MAP(n) case MEP_OPERAND_##n: return BFD_RELOC_MEP_##n; 1473#else 1474#define MAP(n) case MEP_OPERAND_/**/n: return BFD_RELOC_MEP_/**/n; 1475#endif 1476 1477bfd_reloc_code_real_type 1478md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED, 1479 const CGEN_OPERAND *operand, 1480 fixS *fixP) 1481{ 1482 enum bfd_reloc_code_real reloc = fixP->fx_cgen.opinfo; 1483 static char printed[MEP_OPERAND_MAX] = { 0 }; 1484 1485 /* If there's a reloc here, it's because the parser saw a %foo() and 1486 is giving us the correct reloc to use, or because we converted to 1487 a different size reloc below and want to avoid "converting" more 1488 than once. */ 1489 if (reloc && reloc != BFD_RELOC_NONE) 1490 return reloc; 1491 1492 switch (operand->type) 1493 { 1494 MAP (PCREL8A2); /* beqz */ 1495 MAP (PCREL12A2); /* bsr16 */ 1496 MAP (PCREL17A2); /* beqi */ 1497 MAP (PCREL24A2); /* bsr24 */ 1498 MAP (PCABS24A2); /* jmp */ 1499 MAP (UIMM24); /* mov */ 1500 MAP (ADDR24A4); /* sw/lw */ 1501 1502 /* The rest of the relocs should be generated by the parser, 1503 for things such as %tprel(), etc. */ 1504 case MEP_OPERAND_SIMM16: 1505#ifdef OBJ_COMPLEX_RELC 1506 /* coalescing this into RELOC_MEP_16 is actually a bug, 1507 since it's a signed operand. let the relc code handle it. */ 1508 return BFD_RELOC_RELC; 1509#endif 1510 1511 case MEP_OPERAND_UIMM16: 1512 case MEP_OPERAND_SDISP16: 1513 case MEP_OPERAND_CODE16: 1514 fixP->fx_where += 2; 1515 /* to avoid doing the above add twice */ 1516 fixP->fx_cgen.opinfo = BFD_RELOC_MEP_16; 1517 return BFD_RELOC_MEP_16; 1518 1519 default: 1520#ifdef OBJ_COMPLEX_RELC 1521 /* this is not an error, yet. 1522 pass it to the linker. */ 1523 return BFD_RELOC_RELC; 1524#endif 1525 if (printed[operand->type]) 1526 return BFD_RELOC_NONE; 1527 printed[operand->type] = 1; 1528 1529 as_bad_where (fixP->fx_file, fixP->fx_line, 1530 _("Don't know how to relocate plain operands of type %s"), 1531 operand->name); 1532 1533 /* Print some helpful hints for the user. */ 1534 switch (operand->type) 1535 { 1536 case MEP_OPERAND_UDISP7: 1537 case MEP_OPERAND_UDISP7A2: 1538 case MEP_OPERAND_UDISP7A4: 1539 as_bad_where (fixP->fx_file, fixP->fx_line, 1540 _("Perhaps you are missing %%tpoff()?")); 1541 break; 1542 default: 1543 break; 1544 } 1545 return BFD_RELOC_NONE; 1546 } 1547} 1548 1549/* Called while parsing an instruction to create a fixup. 1550 We need to check for HI16 relocs and queue them up for later sorting. */ 1551 1552fixS * 1553mep_cgen_record_fixup_exp (fragS *frag, 1554 int where, 1555 const CGEN_INSN *insn, 1556 int length, 1557 const CGEN_OPERAND *operand, 1558 int opinfo, 1559 expressionS *exp) 1560{ 1561 fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length, 1562 operand, opinfo, exp); 1563 return fixP; 1564} 1565 1566/* Return BFD reloc type from opinfo field in a fixS. 1567 It's tricky using fx_r_type in mep_frob_file because the values 1568 are BFD_RELOC_UNUSED + operand number. */ 1569#define FX_OPINFO_R_TYPE(f) ((f)->fx_cgen.opinfo) 1570 1571/* Sort any unmatched HI16 relocs so that they immediately precede 1572 the corresponding LO16 reloc. This is called before md_apply_fix and 1573 tc_gen_reloc. */ 1574 1575void 1576mep_frob_file () 1577{ 1578 struct mep_hi_fixup * l; 1579 1580 for (l = mep_hi_fixup_list; l != NULL; l = l->next) 1581 { 1582 segment_info_type * seginfo; 1583 int pass; 1584 1585 assert (FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_HI16 1586 || FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_LO16); 1587 1588 /* Check quickly whether the next fixup happens to be a matching low. */ 1589 if (l->fixp->fx_next != NULL 1590 && FX_OPINFO_R_TYPE (l->fixp->fx_next) == BFD_RELOC_LO16 1591 && l->fixp->fx_addsy == l->fixp->fx_next->fx_addsy 1592 && l->fixp->fx_offset == l->fixp->fx_next->fx_offset) 1593 continue; 1594 1595 /* Look through the fixups for this segment for a matching 1596 `low'. When we find one, move the high just in front of it. 1597 We do this in two passes. In the first pass, we try to find 1598 a unique `low'. In the second pass, we permit multiple 1599 high's relocs for a single `low'. */ 1600 seginfo = seg_info (l->seg); 1601 for (pass = 0; pass < 2; pass++) 1602 { 1603 fixS * f; 1604 fixS * prev; 1605 1606 prev = NULL; 1607 for (f = seginfo->fix_root; f != NULL; f = f->fx_next) 1608 { 1609 /* Check whether this is a `low' fixup which matches l->fixp. */ 1610 if (FX_OPINFO_R_TYPE (f) == BFD_RELOC_LO16 1611 && f->fx_addsy == l->fixp->fx_addsy 1612 && f->fx_offset == l->fixp->fx_offset 1613 && (pass == 1 1614 || prev == NULL 1615 || (FX_OPINFO_R_TYPE (prev) != BFD_RELOC_HI16) 1616 || prev->fx_addsy != f->fx_addsy 1617 || prev->fx_offset != f->fx_offset)) 1618 { 1619 fixS ** pf; 1620 1621 /* Move l->fixp before f. */ 1622 for (pf = &seginfo->fix_root; 1623 * pf != l->fixp; 1624 pf = & (* pf)->fx_next) 1625 assert (* pf != NULL); 1626 1627 * pf = l->fixp->fx_next; 1628 1629 l->fixp->fx_next = f; 1630 if (prev == NULL) 1631 seginfo->fix_root = l->fixp; 1632 else 1633 prev->fx_next = l->fixp; 1634 1635 break; 1636 } 1637 1638 prev = f; 1639 } 1640 1641 if (f != NULL) 1642 break; 1643 1644 if (pass == 1) 1645 as_warn_where (l->fixp->fx_file, l->fixp->fx_line, 1646 _("Unmatched high relocation")); 1647 } 1648 } 1649} 1650 1651/* See whether we need to force a relocation into the output file. */ 1652 1653int 1654mep_force_relocation (fixS *fixp) 1655{ 1656 if ( fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT 1657 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) 1658 return 1; 1659 1660 /* Allow branches to global symbols to be resolved at assembly time. 1661 This is consistent with way relaxable branches are handled, since 1662 branches to both global and local symbols are relaxed. It also 1663 corresponds to the assumptions made in md_pcrel_from_section. */ 1664 return S_FORCE_RELOC (fixp->fx_addsy, !fixp->fx_pcrel); 1665} 1666 1667/* Write a value out to the object file, using the appropriate endianness. */ 1668 1669void 1670md_number_to_chars (char *buf, valueT val, int n) 1671{ 1672 if (target_big_endian) 1673 number_to_chars_bigendian (buf, val, n); 1674 else 1675 number_to_chars_littleendian (buf, val, n); 1676} 1677 1678/* Turn a string in input_line_pointer into a floating point constant 1679 of type type, and store the appropriate bytes in *litP. The number 1680 of LITTLENUMS emitted is stored in *sizeP . An error message is 1681 returned, or NULL on OK. */ 1682 1683/* Equal to MAX_PRECISION in atof-ieee.c */ 1684#define MAX_LITTLENUMS 6 1685 1686char * 1687md_atof (int type, char *litP, int *sizeP) 1688{ 1689 int i; 1690 int prec; 1691 LITTLENUM_TYPE words [MAX_LITTLENUMS]; 1692 char * t; 1693 1694 switch (type) 1695 { 1696 case 'f': 1697 case 'F': 1698 case 's': 1699 case 'S': 1700 prec = 2; 1701 break; 1702 1703 case 'd': 1704 case 'D': 1705 case 'r': 1706 case 'R': 1707 prec = 4; 1708 break; 1709 1710 /* FIXME: Some targets allow other format chars for bigger sizes here. */ 1711 default: 1712 *sizeP = 0; 1713 return _("Bad call to md_atof()"); 1714 } 1715 1716 t = atof_ieee (input_line_pointer, type, words); 1717 if (t) 1718 input_line_pointer = t; 1719 * sizeP = prec * sizeof (LITTLENUM_TYPE); 1720 1721 for (i = 0; i < prec; i++) 1722 { 1723 md_number_to_chars (litP, (valueT) words[i], 1724 sizeof (LITTLENUM_TYPE)); 1725 litP += sizeof (LITTLENUM_TYPE); 1726 } 1727 1728 return 0; 1729} 1730 1731 1732bfd_boolean 1733mep_fix_adjustable (fixS *fixP) 1734{ 1735 bfd_reloc_code_real_type reloc_type; 1736 1737 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED) 1738 { 1739 const CGEN_INSN *insn = NULL; 1740 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED; 1741 const CGEN_OPERAND *operand 1742 = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex); 1743 reloc_type = md_cgen_lookup_reloc (insn, operand, fixP); 1744 } 1745 else 1746 reloc_type = fixP->fx_r_type; 1747 1748 if (fixP->fx_addsy == NULL) 1749 return 1; 1750 1751 /* Prevent all adjustments to global symbols. */ 1752 if (S_IS_EXTERNAL (fixP->fx_addsy)) 1753 return 0; 1754 1755 if (S_IS_WEAK (fixP->fx_addsy)) 1756 return 0; 1757 1758 /* We need the symbol name for the VTABLE entries */ 1759 if (reloc_type == BFD_RELOC_VTABLE_INHERIT 1760 || reloc_type == BFD_RELOC_VTABLE_ENTRY) 1761 return 0; 1762 1763 return 1; 1764} 1765 1766int 1767mep_elf_section_letter (int letter, char **ptrmsg) 1768{ 1769 if (letter == 'v') 1770 return SHF_MEP_VLIW; 1771 1772 *ptrmsg = _("Bad .section directive: want a,v,w,x,M,S in string"); 1773 return 0; 1774} 1775 1776flagword 1777mep_elf_section_flags (flagword flags, int attr, int type ATTRIBUTE_UNUSED) 1778{ 1779 if (attr & SHF_MEP_VLIW) 1780 flags |= SEC_MEP_VLIW; 1781 return flags; 1782} 1783 1784/* In vliw mode, the default section is .vtext. We have to be able 1785 to switch into .vtext using only the .vtext directive. */ 1786 1787static segT 1788mep_vtext_section (void) 1789{ 1790 static segT vtext_section; 1791 1792 if (! vtext_section) 1793 { 1794 flagword applicable = bfd_applicable_section_flags (stdoutput); 1795 vtext_section = subseg_new (VTEXT_SECTION_NAME, 0); 1796 bfd_set_section_flags (stdoutput, vtext_section, 1797 applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC 1798 | SEC_CODE | SEC_READONLY 1799 | SEC_MEP_VLIW)); 1800 } 1801 1802 return vtext_section; 1803} 1804 1805static void 1806mep_s_vtext (int ignore ATTRIBUTE_UNUSED) 1807{ 1808 int temp; 1809 1810 /* Record previous_section and previous_subsection. */ 1811 obj_elf_section_change_hook (); 1812 1813 temp = get_absolute_expression (); 1814 subseg_set (mep_vtext_section (), (subsegT) temp); 1815 demand_empty_rest_of_line (); 1816} 1817 1818static void 1819mep_switch_to_core_mode (int dummy ATTRIBUTE_UNUSED) 1820{ 1821 mep_process_saved_insns (); 1822 pluspresent = 0; 1823 mode = CORE; 1824} 1825 1826static void 1827mep_switch_to_vliw_mode (int dummy ATTRIBUTE_UNUSED) 1828{ 1829 if (! MEP_VLIW) 1830 as_bad (_(".vliw unavailable when VLIW is disabled.")); 1831 mode = VLIW; 1832 /* Switch into .vtext here too. */ 1833 /* mep_s_vtext(); */ 1834} 1835 1836/* This is an undocumented pseudo-op used to disable gas's 1837 "disabled_registers" check. Used for code which checks for those 1838 registers at runtime. */ 1839static void 1840mep_noregerr (int i ATTRIBUTE_UNUSED) 1841{ 1842 allow_disabled_registers = 1; 1843} 1844 1845/* mep_unrecognized_line: This is called when a line that can't be parsed 1846 is encountered. We use it to check for a leading '+' sign which indicates 1847 that the current instruction is a coprocessor instruction that is to be 1848 parallelized with a previous core insn. This function accepts the '+' and 1849 rejects all other characters that might indicate garbage at the beginning 1850 of the line. The '+' character gets lost as the calling loop continues, 1851 so we need to indicate that we saw it. */ 1852 1853int 1854mep_unrecognized_line (int ch) 1855{ 1856 switch (ch) 1857 { 1858 case '+': 1859 pluspresent = 1; 1860 return 1; /* '+' indicates an instruction to be parallelized. */ 1861 default: 1862 return 0; /* If it's not a '+', the line can't be parsed. */ 1863 } 1864} 1865 1866void 1867mep_cleanup (void) 1868{ 1869 /* Take care of any insns left to be parallelized when the file ends. 1870 This is mainly here to handle the case where the file ends with an 1871 insn preceeded by a + or the file ends unexpectedly. */ 1872 if (mode == VLIW) 1873 mep_process_saved_insns (); 1874} 1875 1876int 1877mep_flush_pending_output (void) 1878{ 1879 if (mode == VLIW) 1880 { 1881 mep_process_saved_insns (); 1882 pluspresent = 0; 1883 } 1884 1885 return 1; 1886} 1887