return error;
}
+/* Similar to riscv_ip, but assembles an instruction according to the
+ hardcode values of .insn directive. */
+
+static const char *
+riscv_ip_hardcode (char *str,
+ struct riscv_cl_insn *ip,
+ expressionS *imm_expr,
+ const char *error)
+{
+ struct riscv_opcode *insn;
+ insn_t values[2] = {0, 0};
+ unsigned int num = 0;
+
+ input_line_pointer = str;
+ do
+ {
+ expression (imm_expr);
+ if (imm_expr->X_op != O_constant)
+ {
+ /* The first value isn't constant, so it should be
+ .insn <type> <operands>. We have been parsed it
+ in the riscv_ip. */
+ if (num == 0)
+ return error;
+ return _("values must be constant");
+ }
+ values[num++] = (insn_t) imm_expr->X_add_number;
+ }
+ while (*input_line_pointer++ == ',' && num < 2);
+
+ input_line_pointer--;
+ if (*input_line_pointer != '\0')
+ return _("unrecognized values");
+
+ insn = XNEW (struct riscv_opcode);
+ insn->match = values[num - 1];
+ create_insn (ip, insn);
+ unsigned int bytes = riscv_insn_length (insn->match);
+ if (values[num - 1] >> (8 * bytes) != 0
+ || (num == 2 && values[0] != bytes))
+ return _("value conflicts with instruction length");
+
+ return NULL;
+}
+
void
md_assemble (char *str)
{
return s_leb128 (sign);
}
-/* Parse the .insn directive. */
+/* Parse the .insn directive. There are three formats,
+ Format 1: .insn <type> <operand1>, <operand2>, ...
+ Format 2: .insn <length>, <value>
+ Format 3: .insn <value>. */
static void
s_riscv_insn (int x ATTRIBUTE_UNUSED)
const char *error = riscv_ip (str, &insn, &imm_expr,
&imm_reloc, insn_type_hash);
-
if (error)
{
- as_bad ("%s `%s'", error, str);
+ char *save_in = input_line_pointer;
+ error = riscv_ip_hardcode (str, &insn, &imm_expr, error);
+ input_line_pointer = save_in;
}
+
+ if (error)
+ as_bad ("%s `%s'", error, str);
else
{
gas_assert (insn.insn_mo->pinfo != INSN_MACRO);
Enables or disables the CSR checking.
@cindex INSN directives
-@item .insn @var{value}
+@item .insn @var{type}, @var{operand} [,...,@var{operand_n}]
+@itemx .insn @var{insn_length}, @var{value}
@itemx .insn @var{value}
This directive permits the numeric representation of an instructions
and makes the assembler insert the operands according to one of the
instruction formats for @samp{.insn} (@ref{RISC-V-Formats}).
For example, the instruction @samp{add a0, a1, a2} could be written as
-@samp{.insn r 0x33, 0, 0, a0, a1, a2}.
+@samp{.insn r 0x33, 0, 0, a0, a1, a2}. But in fact, the instruction
+formats are difficult to use for some users, so most of them are using
+@samp{.word} to encode the instruction directly, rather than using
+@samp{.insn}. It is fine for now, but will be wrong when the mapping
+symbols are supported, since @samp{.word} will not be shown as an
+instruction, it should be shown as data. Therefore, we also support
+two more formats of the @samp{.insn}, the instruction @samp{add a0, a1, a2}
+could also be written as @samp{.insn 0x4, 0xc58533} or @samp{.insn 0xc58533}.
+When the @var{insn_length} is set, then assembler will check if the
+@var{value} is a valid @var{insn_length} bytes instruction.
@cindex @code{.attribute} directive, RISC-V
@item .attribute @var{tag}, @var{value}
--- /dev/null
+#as:
+#source: insn-fail.s
+#error_output: insn-fail.l
--- /dev/null
+.*Assembler messages:
+.*Error: unrecognized opcode `r,0x00000013'
+.*Error: values must be constant `0x4,rs1'
+.*Error: unrecognized values `0x4 0x5'
+.*Error: unrecognized values `0x4,0x5,0x6'
+.*Error: value conflicts with instruction length `0x4,0x0001'
+.*Error: value conflicts with instruction length `0x2,0x00000013'
--- /dev/null
+ .insn r, 0x00000013
+ .insn 0x4, rs1
+ .insn 0x4 0x5
+ .insn 0x4, 0x5, 0x6
+ .insn 0x4, 0x0001
+ .insn 0x2, 0x00000013
[^:]+:[ ]+00c58533[ ]+add[ ]+a0,a1,a2
[^:]+:[ ]+00c58533[ ]+add[ ]+a0,a1,a2
[^:]+:[ ]+00c58533[ ]+add[ ]+a0,a1,a2
+[^:]+:[ ]+0001[ ]+nop
+[^:]+:[ ]+00000013[ ]+nop
+[^:]+:[ ]+00000057[ ]+0x57
+[^:]+:[ ]+0001[ ]+nop
+[^:]+:[ ]+00000013[ ]+nop
+[^:]+:[ ]+00000057[ ]+0x57
.insn r 0x33, 0, 0, fa0, a1, fa2
.insn r 0x33, 0, 0, a0, fa1, fa2
.insn r 0x33, 0, 0, fa0, fa1, fa2
+
+ .insn 0x0001
+ .insn 0x00000013
+ .insn 0x00000057
+ .insn 0x2, 0x0001
+ .insn 0x4, 0x00000013
+ .insn 0x4, 0x00000057