X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-rl78.c;h=bd964dc163003d9222a04c0499230ac3eee68d45;hb=5c111e376966558968049df5839776067729d3c8;hp=fe0f97724f5ba9185db36428c7355627bb447d64;hpb=6652d298c01d1747ad2120f5815905364f3b62f9;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-rl78.c b/gas/config/tc-rl78.c index fe0f97724f..bd964dc163 100644 --- a/gas/config/tc-rl78.c +++ b/gas/config/tc-rl78.c @@ -38,7 +38,9 @@ const char comment_chars[] = ";"; first line of the input file. This is because the compiler outputs #NO_APP at the beginning of its output. */ const char line_comment_chars[] = "#"; -const char line_separator_chars[] = "|"; +/* Use something that isn't going to be needed by any expressions or + other syntax. */ +const char line_separator_chars[] = "@"; const char EXP_CHARS[] = "eE"; const char FLT_CHARS[] = "dD"; @@ -81,6 +83,18 @@ typedef struct rl78_bytesT static rl78_bytesT rl78_bytes; +void +rl78_linkrelax_addr16 (void) +{ + rl78_bytes.link_relax |= RL78_RELAXA_ADDR16; +} + +void +rl78_linkrelax_branch (void) +{ + rl78_bytes.link_relax |= RL78_RELAXA_BRA; +} + static void rl78_fixup (expressionS exp, int offsetbits, int nbits, int type) { @@ -240,19 +254,32 @@ rl78_field (int val, int pos, int sz) /*------------------------------------------------------------------*/ +enum options +{ + OPTION_RELAX = OPTION_MD_BASE, +}; + #define RL78_SHORTOPTS "" const char * md_shortopts = RL78_SHORTOPTS; /* Assembler options. */ struct option md_longopts[] = { + {"relax", no_argument, NULL, OPTION_RELAX}, {NULL, no_argument, NULL, 0} }; size_t md_longopts_size = sizeof (md_longopts); int -md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED) +md_parse_option (int c, char * arg ATTRIBUTE_UNUSED) { + switch (c) + { + case OPTION_RELAX: + linkrelax = 1; + return 1; + + } return 0; } @@ -348,7 +375,37 @@ md_operand (expressionS * exp ATTRIBUTE_UNUSED) void rl78_frag_init (fragS * fragP) { - fragP->tc_frag_data = 0; + if (rl78_bytes.n_relax || rl78_bytes.link_relax) + { + fragP->tc_frag_data = malloc (sizeof (rl78_bytesT)); + memcpy (fragP->tc_frag_data, & rl78_bytes, sizeof (rl78_bytesT)); + } + else + fragP->tc_frag_data = 0; +} + +/* When relaxing, we need to output a reloc for any .align directive + so that we can retain this alignment as we adjust opcode sizes. */ +void +rl78_handle_align (fragS * frag) +{ + if (linkrelax + && (frag->fr_type == rs_align + || frag->fr_type == rs_align_code) + && frag->fr_address + frag->fr_fix > 0 + && frag->fr_offset > 0 + && now_seg != bss_section) + { + fix_new (frag, frag->fr_fix, 0, + &abs_symbol, RL78_RELAXA_ALIGN + frag->fr_offset, + 0, BFD_RELOC_RL78_RELAX); + /* For the purposes of relaxation, this relocation is attached + to the byte *after* the alignment - i.e. the byte that must + remain aligned. */ + fix_new (frag->fr_next, 0, 0, + &abs_symbol, RL78_RELAXA_ELIGN + frag->fr_offset, + 0, BFD_RELOC_RL78_RELAX); + } } char * @@ -391,13 +448,50 @@ md_assemble (char * str) rl78_parse (); - bytes = frag_more (rl78_bytes.n_prefix + rl78_bytes.n_base + rl78_bytes.n_ops); - frag_then = frag_now; + /* This simplifies the relaxation code. */ + if (rl78_bytes.link_relax) + { + int olen = rl78_bytes.n_prefix + rl78_bytes.n_base + rl78_bytes.n_ops; + /* We do it this way because we want the frag to have the + rl78_bytes in it, which we initialize above. */ + bytes = frag_more (olen); + frag_then = frag_now; + frag_variant (rs_machine_dependent, + olen /* max_chars */, + 0 /* var */, + olen /* subtype */, + 0 /* symbol */, + 0 /* offset */, + 0 /* opcode */); + frag_then->fr_opcode = bytes; + frag_then->fr_fix = olen + (bytes - frag_then->fr_literal); + frag_then->fr_subtype = olen; + frag_then->fr_var = 0; + } + else + { + bytes = frag_more (rl78_bytes.n_prefix + rl78_bytes.n_base + rl78_bytes.n_ops); + frag_then = frag_now; + } APPEND (prefix, n_prefix); APPEND (base, n_base); APPEND (ops, n_ops); + if (rl78_bytes.link_relax) + { + fixS * f; + + f = fix_new (frag_then, + (char *) bytes - frag_then->fr_literal, + 0, + abs_section_sym, + rl78_bytes.link_relax | rl78_bytes.n_fixups, + 0, + BFD_RELOC_RL78_RELAX); + frag_then->tc_frag_data->link_relax_fixP = f; + } + for (i = 0; i < rl78_bytes.n_fixups; i ++) { /* index: [nbytes][type] */ @@ -460,6 +554,23 @@ rl78_cons_fix_new (fragS * frag, return; } + switch (exp->X_md) + { + case BFD_RELOC_RL78_LO16: + case BFD_RELOC_RL78_HI16: + if (size != 2) + as_bad (_("%%hi16/%%lo16 only applies to .short or .hword")); + type = exp->X_md; + break; + case BFD_RELOC_RL78_HI8: + if (size != 1) + as_bad (_("%%hi8 only applies to .byte")); + type = exp->X_md; + break; + default: + break; + } + if (exp->X_op == O_subtract && exp->X_op_symbol) { if (size != 4 && size != 2 && size != 1) @@ -477,6 +588,7 @@ md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, segT segment ATTR { return 0; } + arelent ** tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp) { @@ -648,6 +760,10 @@ md_apply_fix (struct fix * f ATTRIBUTE_UNUSED, case BFD_RELOC_NONE: break; + case BFD_RELOC_RL78_RELAX: + f->fx_done = 1; + break; + case BFD_RELOC_8: case BFD_RELOC_8_PCREL: op[0] = val; @@ -696,4 +812,5 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, fragS * fragP ATTRIBUTE_UNUSED) { /* No relaxation yet */ + fragP->fr_var = 0; }