+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.
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.
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
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)
{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
{"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}
};
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);
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);
}
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;
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)
!= (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;
}
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;
}
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