diff options
-rw-r--r-- | gas/ChangeLog | 22 | ||||
-rw-r--r-- | gas/config/tc-cris.c | 70 | ||||
-rw-r--r-- | gas/doc/c-cris.texi | 19 |
3 files changed, 108 insertions, 3 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 58101a8..496b578 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,25 @@ +2004-03-22 Hans-Peter Nilsson <hp@axis.com> + + * doc/c-cris.texi (CRIS-Opts): Document --no-mul-bug-abort, + --mul-bug-abort and the default behavior. + * config/tc-cris.c (cris_insn_kind): New member CRIS_INSN_MUL. + (err_for_dangerous_mul_placement): New variable. + (STATE_MUL, OPTION_MULBUG_ABORT_ON, OPTION_MULBUG_ABORT_OFF): New + macros. + (md_cris_relax_table): Have placeholder for STATE_MUL. + (md_longopts): New options --mul-bug-abort and --no-mul-bug-abort. + (cris_relax_frag) <case ENCODE_RELAX (STATE_MUL, STATE_BYTE)>: New + case doing nothing. + (md_estimate_size_before_relax) <case ENCODE_RELAX (STATE_MUL, + STATE_BYTE)>: Ditto. + (md_convert_frag) <ENCODE_RELAX (STATE_MUL, STATE_BYTE)>: Check + alignment and position of this frag, emit error message if + suspicious. + (md_assemble): For a multiply insn and when checking it, + transform the current frag into a special frag for that purpose. + (md_parse_option) <case OPTION_MULBUG_ABORT_OFF, case + OPTION_MULBUG_ABORT_ON>: Handle new options. + 2004-03-19 Bob Wilson <bob.wilson@acm.org> * config/tc-xtensa.c (mark_literal_frags): New function. diff --git a/gas/config/tc-cris.c b/gas/config/tc-cris.c index 736261c..e725b88 100644 --- a/gas/config/tc-cris.c +++ b/gas/config/tc-cris.c @@ -58,7 +58,7 @@ Note that some prefix-insns might be assembled as CRIS_INSN_NORMAL. */ enum cris_insn_kind { - CRIS_INSN_NORMAL, CRIS_INSN_NONE, CRIS_INSN_BRANCH + CRIS_INSN_NORMAL, CRIS_INSN_NONE, CRIS_INSN_BRANCH, CRIS_INSN_MUL }; /* An instruction will have one of these prefixes. @@ -187,6 +187,10 @@ const pseudo_typeS md_pseudo_table[] = static int warn_for_branch_expansion = 0; +/* Whether to emit error when a MULS/MULU could be located last on a + cache-line. */ +static int err_for_dangerous_mul_placement = 1; + const char cris_comment_chars[] = ";"; /* This array holds the chars that only start a comment at the beginning of @@ -219,10 +223,16 @@ const char FLT_CHARS[] = ""; length: byte, word, 10-byte expansion 2. BDAP - length: byte, word, dword */ + length: byte, word, dword + + 3. MULS/MULU + Not really a relaxation (no infrastructure to get delay-slots + right), just an alignment and placement checker for the v10 + multiply/cache-bug. */ #define STATE_CONDITIONAL_BRANCH (1) #define STATE_BASE_PLUS_DISP_PREFIX (2) +#define STATE_MUL (3) #define STATE_LENGTH_MASK (3) #define STATE_BYTE (0) @@ -282,7 +292,13 @@ const relax_typeS md_cris_relax_table[] = {BDAP_WF, BDAP_WB, 2, ENCODE_RELAX (2, 2)}, /* BDAP.d [PC+] (2, 2). */ - {0, 0, 4, 0} + {0, 0, 4, 0}, + + /* Unused (2, 3). */ + {0, 0, 0, 0}, + + /* MULS/MULU (3, 0). Positions (3, 1..3) are unused. */ + {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0} }; #undef BRANCH_BF @@ -304,6 +320,10 @@ struct option md_longopts[] = {"underscore", no_argument, NULL, OPTION_US}, #define OPTION_PIC (OPTION_MD_BASE + 2) {"pic", no_argument, NULL, OPTION_PIC}, +#define OPTION_MULBUG_ABORT_ON (OPTION_MD_BASE + 3) + {"mul-bug-abort", no_argument, NULL, OPTION_MULBUG_ABORT_ON}, +#define OPTION_MULBUG_ABORT_OFF (OPTION_MD_BASE + 4) + {"no-mul-bug-abort", no_argument, NULL, OPTION_MULBUG_ABORT_OFF}, {NULL, no_argument, NULL, 0} }; @@ -392,6 +412,10 @@ cris_relax_frag (seg, fragP, stretch) aim = S_GET_VALUE (symbolP); break; + case ENCODE_RELAX (STATE_MUL, STATE_BYTE): + /* Nothing to do here. */ + return 0; + default: as_fatal (_("internal inconsistency problem in %s: fr_subtype %d"), __FUNCTION__, fragP->fr_subtype); @@ -558,6 +582,10 @@ md_estimate_size_before_relax (fragP, segment_type) fragP->fr_var = md_cris_relax_table[fragP->fr_subtype].rlx_length; break; + case ENCODE_RELAX (STATE_MUL, STATE_BYTE): + /* Nothing to do here. */ + break; + default: BAD_CASE (fragP->fr_subtype); } @@ -679,6 +707,24 @@ md_convert_frag (abfd, sec, fragP) var_part_size = 4; break; + case ENCODE_RELAX (STATE_MUL, STATE_BYTE): + /* This is the only time we check position and aligmnent of the + placement-tracking frag. */ + if (sec->alignment_power < 2) + as_bad_where (fragP->fr_file, fragP->fr_line, + _("section alignment must be >= 4 bytes to check MULS/MULU safeness")); + else + { + /* If the address after the MULS/MULU has alignment which is + that of the section and may be that of a cache-size of the + buggy versions, then the MULS/MULU can be placed badly. */ + if ((address_of_var_part + & ((1 << sec->alignment_power) - 1) & 31) == 0) + as_bad_where (fragP->fr_file, fragP->fr_line, + _("dangerous MULS/MULU location; give it higher alignment")); + } + break; + default: BAD_CASE (fragP->fr_subtype); break; @@ -967,6 +1013,13 @@ md_assemble (str) output_instruction.expr.X_add_number); } } + else if (output_instruction.insn_type == CRIS_INSN_MUL + && err_for_dangerous_mul_placement) + /* Create a frag which which we track the location of the mul insn + (in the last two bytes before the mul-frag). */ + frag_variant (rs_machine_dependent, 0, 0, + ENCODE_RELAX (STATE_MUL, STATE_BYTE), + NULL, 0, opcodep); else { if (output_instruction.imm_oprnd_size > 0) @@ -1572,6 +1625,9 @@ cris_process_instruction (insn_text, out_insnp, prefixp) != (unsigned int) out_insnp->imm_oprnd_size)) as_bad (_("PIC relocation size does not match operand size")); } + else if (instruction->op == cris_muls_op + || instruction->op == cris_mulu_op) + out_insnp->insn_type = CRIS_INSN_MUL; } break; } @@ -2947,6 +3003,14 @@ md_parse_option (arg, argp) pic = TRUE; return 1; + case OPTION_MULBUG_ABORT_OFF: + err_for_dangerous_mul_placement = 0; + return 1; + + case OPTION_MULBUG_ABORT_ON: + err_for_dangerous_mul_placement = 1; + return 1; + default: return 0; } diff --git a/gas/doc/c-cris.texi b/gas/doc/c-cris.texi index 2551b18..e814767 100644 --- a/gas/doc/c-cris.texi +++ b/gas/doc/c-cris.texi @@ -74,6 +74,25 @@ When @option{-N} is specified, @code{@value{AS}} will emit a warning when a 16-bit branch instruction is expanded into a 32-bit multiple-instruction construct (@pxref{CRIS-Expand}). +@cindex @option{--no-mul-bug-abort} command line option, CRIS +@cindex @option{--mul-bug-abort} command line option, CRIS +@cindex CRIS @option{--no-mul-bug-abort} command line option +@cindex CRIS @option{--mul-bug-abort} command line option + +Some versions of the CRIS v10, for example in the Etrax 100 LX, +contain a bug that causes destabilizing memory accesses when a +multiply instruction is executed with certain values in the +first operand just before a cache-miss. When the +@option{--mul-bug-abort} command line option is active (the +default value), @code{@value{AS}} will refuse to assemble a file +containing a multiply instruction at a dangerous offset, one +that could be the last on a cache-line, or is in a section with +insufficient alignment. This placement checking does not catch +any case where the multiply instruction is dangerously placed +because it is located in a delay-slot. The +@option{--mul-bug-abort} command line option turns off the +checking. + @node CRIS-Expand @section Instruction expansion |