diff options
author | DJ Delorie <dj@redhat.com> | 2011-12-23 01:49:37 +0000 |
---|---|---|
committer | DJ Delorie <dj@redhat.com> | 2011-12-23 01:49:37 +0000 |
commit | 9cea966c22d3db4ed4d7008241103b05105c17d3 (patch) | |
tree | 8359d5706f5393400b3b021d84095e357fac9f81 /gas/config/rl78-parse.y | |
parent | 23cb30dead402c95346474691469528cb199767b (diff) | |
download | gdb-9cea966c22d3db4ed4d7008241103b05105c17d3.zip gdb-9cea966c22d3db4ed4d7008241103b05105c17d3.tar.gz gdb-9cea966c22d3db4ed4d7008241103b05105c17d3.tar.bz2 |
[bfd]
* elf32-rl78.c (rl78_elf_howto_table): Add R_RL78_RH_RELAX.
(rl78_reloc_map): Add BFD_RELOC_RL78_RELAX.
(rl78_elf_relocate_section): Add R_RL78_RH_RELAX, R_RL78_RH_SFR,
and R_RL78_RH_SADDR.
(rl78_elf_finish_dynamic_sections): Only validate PLT section if
we didn't relax anything, as relaxing might remove a PLT reference
after we've set up the table.
(elf32_rl78_relax_delete_bytes): New.
(reloc_bubblesort): New.
(rl78_offset_for_reloc): New.
(relax_addr16): New.
(rl78_elf_relax_section): Add support for relaxing long
instructions into short ones.
[gas]
* config/rl78-defs.h (rl78_linkrelax_addr16): Add.
(rl78_linkrelax_dsp, rl78_linkrelax_imm): Remove.
* config/rl78-parse.y: Tag all addr16 and branch patterns with
relaxation markers.
* config/tc-rl78.c (rl78_linkrelax_addr16): New.
(rl78_linkrelax_branch): New.
(OPTION_RELAX): New.
(md_longopts): Add relax option.
(md_parse_option): Add OPTION_RELAX.
(rl78_frag_init): Support relaxation.
(rl78_handle_align): New.
(md_assemble): Support relaxation.
(md_apply_fix): Likewise.
(md_convert_frag): Likewise.
* config/tc-rl78.h (MAX_MEM_FOR_RS_ALIGN_CODE): New.
(HANDLE_ALIGN): New.
(rl78_handle_align): Declare.
* config/rl78-parse.y (rl78_bit_insn): New. Set it for all bit
insn patterns.
(find_bit_index): New. Strip .BIT suffix off relevent
expressions for bit insns.
(rl78_lex): Exclude bit suffixes from expression parsing.
[include/elf]
* rl78.h (R_RL78_RH_RELAX, R_RL78_RH_SFR, R_RL78_RH_SADDR): New.
(RL78_RELAXA_BRA, RL78_RELAXA_ADDR16: New.
Diffstat (limited to 'gas/config/rl78-parse.y')
-rw-r--r-- | gas/config/rl78-parse.y | 152 |
1 files changed, 104 insertions, 48 deletions
diff --git a/gas/config/rl78-parse.y b/gas/config/rl78-parse.y index 4bfb3ff..d5f2ec9 100644 --- a/gas/config/rl78-parse.y +++ b/gas/config/rl78-parse.y @@ -89,6 +89,7 @@ static int rl78_in_brackets = 0; static int rl78_last_token = 0; static char * rl78_init_start; static char * rl78_last_exp_start = 0; +static int rl78_bit_insn = 0; #define YYDEBUG 1 #define YYERROR_VERBOSE 1 @@ -218,7 +219,7 @@ statement : { B1 (0x0b|$1); O1 ($4); } | addsub A ',' opt_es '!' EXPR - { B1 (0x0f|$1); O2 ($6); } + { B1 (0x0f|$1); O2 ($6); rl78_linkrelax_addr16 (); } | addsub A ',' opt_es '[' HL ']' { B1 (0x0d|$1); } @@ -238,7 +239,7 @@ statement : { if ($1 != 0x40) { rl78_error ("Only CMP takes these operands"); } else - { B1 (0x00|$1); O2 ($4); O1 ($7); } + { B1 (0x00|$1); O2 ($4); O1 ($7); rl78_linkrelax_addr16 (); } } /* ---------------------------------------------------------------------- */ @@ -253,7 +254,7 @@ statement : { B1 (0x06|$1); O1 ($4); } | addsubw AX ',' opt_es '!' EXPR - { B1 (0x02|$1); O2 ($6); } + { B1 (0x02|$1); O2 ($6); rl78_linkrelax_addr16 (); } | addsubw AX ',' opt_es '[' HL '+' EXPR ']' { B2 (0x61, 0x09|$1); O1 ($8); } @@ -336,13 +337,13 @@ statement : { B1 (0xef); PC1 ($3); } | BR '$' '!' EXPR - { B1 (0xee); PC2 ($4); } + { B1 (0xee); PC2 ($4); rl78_linkrelax_branch (); } | BR '!' EXPR - { B1 (0xed); O2 ($3); } + { B1 (0xed); O2 ($3); rl78_linkrelax_branch (); } | BR '!' '!' EXPR - { B1 (0xec); O3 ($4); } + { B1 (0xec); O3 ($4); rl78_linkrelax_branch (); } /* ---------------------------------------------------------------------- */ @@ -364,7 +365,7 @@ statement : { B1 (0xfd); O2 ($3); } | CALL '!' '!' EXPR - { B1 (0xfc); O3 ($4); } + { B1 (0xfc); O3 ($4); rl78_linkrelax_branch (); } | CALLT '[' EXPR ']' { if ($3.X_op != O_constant) @@ -406,7 +407,7 @@ statement : { B2 (0x71, 0x8a|$1); FE ($4, 9, 3); } | setclr1 opt_es '!' EXPR '.' EXPR - { B2 (0x71, 0x00+$1*0x08); FE ($6, 9, 3); O2 ($4); } + { B2 (0x71, 0x00+$1*0x08); FE ($6, 9, 3); O2 ($4); rl78_linkrelax_addr16 (); } | setclr1 opt_es '[' HL ']' '.' EXPR { B2 (0x71, 0x82|$1); FE ($7, 9, 3); } @@ -426,7 +427,7 @@ statement : { B1 (0xe4|$1); O1 ($2); } | oneclrb opt_es '!' EXPR - { B1 (0xe5|$1); O2 ($4); } + { B1 (0xe5|$1); O2 ($4); rl78_linkrelax_addr16 (); } /* ---------------------------------------------------------------------- */ @@ -453,7 +454,7 @@ statement : { B1 (0xd4); O1 ($2); } | CMP0 opt_es '!' EXPR - { B1 (0xd5); O2 ($4); } + { B1 (0xd5); O2 ($4); rl78_linkrelax_addr16 (); } /* ---------------------------------------------------------------------- */ @@ -468,7 +469,7 @@ statement : | incdec EXPR {SA($2)} { B1 (0xa4|$1); O1 ($2); } | incdec '!' EXPR - { B1 (0xa0|$1); O2 ($3); } + { B1 (0xa0|$1); O2 ($3); rl78_linkrelax_addr16 (); } | incdec ES ':' '!' EXPR { B2 (0x11, 0xa0|$1); O2 ($5); } | incdec '[' HL '+' EXPR ']' @@ -485,7 +486,7 @@ statement : { B1 (0xa6|$1); O1 ($2); } | incdecw opt_es '!' EXPR - { B1 (0xa2|$1); O2 ($4); } + { B1 (0xa2|$1); O2 ($4); rl78_linkrelax_addr16 (); } | incdecw opt_es '[' HL '+' EXPR ']' { B2 (0x61, 0x79+$1); O1 ($6); } @@ -553,7 +554,7 @@ statement : } | MOV '!' EXPR ',' '#' EXPR - { B1 (0xcf); O2 ($3); O1 ($6); } + { B1 (0xcf); O2 ($3); O1 ($6); rl78_linkrelax_addr16 (); } | MOV ES ':' '!' EXPR ',' '#' EXPR { B2 (0x11, 0xcf); O2 ($5); O1 ($8); } @@ -574,16 +575,16 @@ statement : } | MOV A ',' opt_es '!' EXPR - { B1 (0x8f); O2 ($6); } + { B1 (0x8f); O2 ($6); rl78_linkrelax_addr16 (); } | MOV '!' EXPR ',' A - { B1 (0x9f); O2 ($3); } + { B1 (0x9f); O2 ($3); rl78_linkrelax_addr16 (); } | MOV ES ':' '!' EXPR ',' A { B2 (0x11, 0x9f); O2 ($5); } | MOV regb_na ',' opt_es '!' EXPR - { B1 (0xc9|reg_xbc($2)); O2 ($6); } + { B1 (0xc9|reg_xbc($2)); O2 ($6); rl78_linkrelax_addr16 (); } | MOV A ',' opt_es EXPR {NOT_ES} { if (expr_is_saddr ($5)) @@ -712,7 +713,7 @@ statement : /* ---------------------------------------------------------------------- */ - | MOV1 CY ',' EXPR '.' EXPR + | mov1 CY ',' EXPR '.' EXPR { if (expr_is_saddr ($4)) { B2 (0x71, 0x04); FE ($6, 9, 3); O1 ($4); } else if (expr_is_sfr ($4)) @@ -721,16 +722,16 @@ statement : NOT_SFR_OR_SADDR; } - | MOV1 CY ',' A '.' EXPR + | mov1 CY ',' A '.' EXPR { B2 (0x71, 0x8c); FE ($6, 9, 3); } - | MOV1 CY ',' sfr '.' EXPR + | mov1 CY ',' sfr '.' EXPR { B3 (0x71, 0x0c, $4); FE ($6, 9, 3); } - | MOV1 CY ',' opt_es '[' HL ']' '.' EXPR + | mov1 CY ',' opt_es '[' HL ']' '.' EXPR { B2 (0x71, 0x84); FE ($9, 9, 3); } - | MOV1 EXPR '.' EXPR ',' CY + | mov1 EXPR '.' EXPR ',' CY { if (expr_is_saddr ($2)) { B2 (0x71, 0x01); FE ($4, 9, 3); O1 ($2); } else if (expr_is_sfr ($2)) @@ -739,13 +740,13 @@ statement : NOT_SFR_OR_SADDR; } - | MOV1 A '.' EXPR ',' CY + | mov1 A '.' EXPR ',' CY { B2 (0x71, 0x89); FE ($4, 9, 3); } - | MOV1 sfr '.' EXPR ',' CY + | mov1 sfr '.' EXPR ',' CY { B3 (0x71, 0x09, $2); FE ($4, 9, 3); } - | MOV1 opt_es '[' HL ']' '.' EXPR ',' CY + | mov1 opt_es '[' HL ']' '.' EXPR ',' CY { B2 (0x71, 0x81); FE ($7, 9, 3); } /* ---------------------------------------------------------------------- */ @@ -795,10 +796,10 @@ statement : { B1 (0x10); F ($2, 5, 2); } | MOVW AX ',' opt_es '!' EXPR - { B1 (0xaf); O2 ($6); WA($6); } + { B1 (0xaf); O2 ($6); WA($6); rl78_linkrelax_addr16 (); } | MOVW opt_es '!' EXPR ',' AX - { B1 (0xbf); O2 ($4); WA($4); } + { B1 (0xbf); O2 ($4); WA($4); rl78_linkrelax_addr16 (); } | MOVW AX ',' opt_es '[' DE ']' { B1 (0xa9); } @@ -864,7 +865,7 @@ statement : { B1 (0xca); F ($2, 2, 2); O1 ($4); WA($4); } | MOVW regw_na ',' opt_es '!' EXPR - { B1 (0xcb); F ($2, 2, 2); O2 ($6); WA($6); } + { B1 (0xcb); F ($2, 2, 2); O2 ($6); WA($6); rl78_linkrelax_addr16 (); } | MOVW SP ',' '#' EXPR { B2 (0xcb, 0xf8); O2 ($5); } @@ -1008,22 +1009,22 @@ statement : /* ---------------------------------------------------------------------- */ | SKC - { B2 (0x61, 0xc8); } + { B2 (0x61, 0xc8); rl78_linkrelax_branch (); } | SKH - { B2 (0x61, 0xe3); } + { B2 (0x61, 0xe3); rl78_linkrelax_branch (); } | SKNC - { B2 (0x61, 0xd8); } + { B2 (0x61, 0xd8); rl78_linkrelax_branch (); } | SKNH - { B2 (0x61, 0xf3); } + { B2 (0x61, 0xf3); rl78_linkrelax_branch (); } | SKNZ - { B2 (0x61, 0xf8); } + { B2 (0x61, 0xf8); rl78_linkrelax_branch (); } | SKZ - { B2 (0x61, 0xe8); } + { B2 (0x61, 0xe8); rl78_linkrelax_branch (); } /* ---------------------------------------------------------------------- */ @@ -1040,7 +1041,7 @@ statement : } | XCH A ',' opt_es '!' EXPR - { B2 (0x61, 0xaa); O2 ($6); } + { B2 (0x61, 0xaa); O2 ($6); rl78_linkrelax_addr16 (); } | XCH A ',' opt_es '[' DE ']' { B2 (0x61, 0xae); } @@ -1142,18 +1143,18 @@ addsubw : ADDW { $$ = 0x00; } | CMPW { $$ = 0x40; } ; -andor1 : AND1 { $$ = 0x05; } - | OR1 { $$ = 0x06; } - | XOR1 { $$ = 0x07; } +andor1 : AND1 { $$ = 0x05; rl78_bit_insn = 1; } + | OR1 { $$ = 0x06; rl78_bit_insn = 1;} + | XOR1 { $$ = 0x07; rl78_bit_insn = 1; } ; -bt_bf : BT { $$ = 0x02; } - | BF { $$ = 0x04; } - | BTCLR { $$ = 0x00; } +bt_bf : BT { $$ = 0x02; rl78_bit_insn = 1;} + | BF { $$ = 0x04; rl78_bit_insn = 1; } + | BTCLR { $$ = 0x00; rl78_bit_insn = 1; } ; -setclr1 : SET1 { $$ = 0; } - | CLR1 { $$ = 1; } +setclr1 : SET1 { $$ = 0; rl78_bit_insn = 1; } + | CLR1 { $$ = 1; rl78_bit_insn = 1; } ; oneclrb : ONEB { $$ = 0x00; } @@ -1172,6 +1173,9 @@ incdecw : INCW { $$ = 0x00; } | DECW { $$ = 0x10; } ; +mov1 : MOV1 { rl78_bit_insn = 1; } + ; + %% /* ====================================================================== */ @@ -1336,14 +1340,54 @@ rl78_lex_init (char * beginning, char * ending) rl78_in_brackets = 0; rl78_last_token = 0; + rl78_bit_insn = 0; + setbuf (stdout, 0); } +/* Return a pointer to the '.' in a bit index expression (like + foo.5), or NULL if none is found. */ +static char * +find_bit_index (char *tok) +{ + char *last_dot = NULL; + char *last_digit = NULL; + while (*tok && *tok != ',') + { + if (*tok == '.') + { + last_dot = tok; + last_digit = NULL; + } + else if (*tok >= '0' && *tok <= '7' + && last_dot != NULL + && last_digit == NULL) + { + last_digit = tok; + } + else if (ISSPACE (*tok)) + { + /* skip */ + } + else + { + last_dot = NULL; + last_digit = NULL; + } + tok ++; + } + if (last_dot != NULL + && last_digit != NULL) + return last_dot; + return NULL; +} + static int rl78_lex (void) { /*unsigned int ci;*/ char * save_input_pointer; + char * bit = NULL; while (ISSPACE (*rl78_lex_start) && rl78_lex_start != rl78_lex_end) @@ -1400,12 +1444,9 @@ rl78_lex (void) bitfields. We check for it specially so we can allow labels with '.' in them. */ - if (*rl78_lex_start == '.' - && ISDIGIT (rl78_lex_start[1]) - && (rl78_last_token == ']' - || rl78_last_token == A - || rl78_last_token == PSW - || rl78_last_token == EXPR)) + if (rl78_bit_insn + && *rl78_lex_start == '.' + && find_bit_index (rl78_lex_start) == rl78_lex_start) { rl78_last_token = *rl78_lex_start; return *rl78_lex_start ++; @@ -1418,11 +1459,26 @@ rl78_lex (void) return *rl78_lex_start ++; } + /* Again, '.' is funny. Look for '.<digit>' at the end of the line + or before a comma, which is a bitfield, not an expression. */ + + if (rl78_bit_insn) + { + bit = find_bit_index (rl78_lex_start); + if (bit) + *bit = 0; + else + bit = NULL; + } + save_input_pointer = input_line_pointer; input_line_pointer = rl78_lex_start; rl78_lval.exp.X_md = 0; expression (&rl78_lval.exp); + if (bit) + *bit = '.'; + rl78_lex_start = input_line_pointer; input_line_pointer = save_input_pointer; rl78_last_token = EXPR; |