Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disassembler: Support special (non-standard) encodings #17

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 123 additions & 17 deletions gas/config/tc-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1329,7 +1329,6 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
case 'j': used_bits |= ENCODE_ITYPE_IMM (-1U); break;
case 'a': used_bits |= ENCODE_JTYPE_IMM (-1U); break;
case 'p': used_bits |= ENCODE_BTYPE_IMM (-1U); break;
case 'f': /* Fall through. */
case 'q': used_bits |= ENCODE_STYPE_IMM (-1U); break;
case 'u': used_bits |= ENCODE_UTYPE_IMM (-1U); break;
case 'z': break; /* Zero immediate. */
Expand All @@ -1356,6 +1355,30 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
goto unknown_validate_operand;
}
break;
case 'W': /* Various operands. */
switch (*++oparg)
{
case 'i':
switch (*++oparg)
{
case 'f': used_bits |= ENCODE_STYPE_IMM (-1U); break;
default:
goto unknown_validate_operand;
}
break;
case 'f':
switch (*++oparg)
{
case 'M': /* Fall through. */
case 'm': USE_BITS (OP_MASK_RM, OP_SH_RM); break;
default:
goto unknown_validate_operand;
}
break;
default:
goto unknown_validate_operand;
}
break;
case 'X': /* Integer immediate. */
{
size_t n;
Expand Down Expand Up @@ -1384,6 +1407,22 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
}
}
break;
case '\\': /* Ignored fields (w/o defaults). */
while (*++oparg)
{
switch (*oparg)
{
case 'd': USE_BITS (OP_MASK_RD, OP_SH_RD); break;
case 's': USE_BITS (OP_MASK_RS1, OP_SH_RS1); break;
case 'j': used_bits |= ENCODE_ITYPE_IMM (-1U); break;
/* fence: fm field. */
case 'f': USE_BITS (OP_MASK_FM, OP_SH_FM); break;
default:
goto unknown_validate_operand;
}
}
--oparg;
break;
default:
unknown_validate_operand:
as_bad (_("internal: bad RISC-V opcode "
Expand Down Expand Up @@ -3371,22 +3410,71 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
imm_expr->X_op = O_absent;
continue;

case 'f': /* Prefetch offset, pseudo S-type but lower 5-bits zero. */
if (riscv_handle_implicit_zero_offset (imm_expr, asarg))
continue;
my_getExpression (imm_expr, asarg);
check_absolute_expr (ip, imm_expr, false);
if (((unsigned) (imm_expr->X_add_number) & 0x1fU)
|| imm_expr->X_add_number >= (signed) RISCV_IMM_REACH / 2
|| imm_expr->X_add_number < -(signed) RISCV_IMM_REACH / 2)
as_bad (_("improper prefetch offset (%ld)"),
(long) imm_expr->X_add_number);
ip->insn_opcode |=
ENCODE_STYPE_IMM ((unsigned) (imm_expr->X_add_number) &
~ 0x1fU);
imm_expr->X_op = O_absent;
asarg = expr_end;
continue;
case 'W': /* Various operands. */
switch (*++oparg)
{
case 'i':
switch (*++oparg)
{
case 'f':
/* Prefetch offset for 'Zicbop' extension.
pseudo S-type but lower 5-bits zero. */
if (riscv_handle_implicit_zero_offset (imm_expr, asarg))
continue;
my_getExpression (imm_expr, asarg);
check_absolute_expr (ip, imm_expr, false);
if (((unsigned) (imm_expr->X_add_number) & 0x1fU)
|| imm_expr->X_add_number >= RISCV_IMM_REACH / 2
|| imm_expr->X_add_number < -RISCV_IMM_REACH / 2)
as_bad (_ ("improper prefetch offset (%ld)"),
(long) imm_expr->X_add_number);
ip->insn_opcode |= ENCODE_STYPE_IMM (
(unsigned) (imm_expr->X_add_number) & ~0x1fU);
imm_expr->X_op = O_absent;
asarg = expr_end;
continue;
default:
goto unknown_riscv_ip_operand;
}
break;
case 'f':
switch (*++oparg)
{
case 'M':
case 'm':
/* Optional rounding mode (widening conversion)
'M': operand either disallowed or not recommended
(considered to be non-useful to normal software).
'm': operand allowed for compatibility reasons
(display a warning instead). */
if (*asarg == '\0')
{
INSERT_OPERAND (RM, *ip, 0);
continue;
}
else if (*asarg == ',' && asarg++
&& arg_lookup (&asarg, riscv_rm,
ARRAY_SIZE (riscv_rm), &regno))
{
INSERT_OPERAND (RM, *ip, regno);
if (*oparg == 'M')
as_bad (_ ("rounding mode cannot be specified "
"on widening conversion"));
else
as_warn (
_ ("specifying a rounding mode is strongly "
"discourged on widening conversion"));
continue;
}
break;
default:
goto unknown_riscv_ip_operand;
}
break;
default:
goto unknown_riscv_ip_operand;
}
break;

case 'X': /* Integer immediate. */
{
Expand Down Expand Up @@ -3439,6 +3527,24 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
}
}
break;

case '\\': /* Ignored fields (w/o defaults). */
while (*++oparg)
{
switch (*oparg)
{
case 'd': /* Ignored RD. */
case 's': /* Ignored RS1. */
case 'j': /* Ignored immediate (I-type). */
case 'f': /* Ignored fence fm field. */
break;
default:
goto unknown_riscv_ip_operand;
}
}
--oparg;
continue;

default:
unknown_riscv_ip_operand:
as_fatal (_("internal: unknown argument type `%s'"),
Expand Down
21 changes: 21 additions & 0 deletions gas/testsuite/gas/riscv/fence-dis-nonstd.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#as: -march=rv32i
#source: fence-dis-nonstd.s
#objdump: -dr

.*:[ ]+file format .*


Disassembly of section .text:

0+000 <target>:
[ ]+[0-9a-f]+:[ ]+0ff0000f[ ]+fence
[ ]+[0-9a-f]+:[ ]+8330000f[ ]+fence\.tso
[ ]+[0-9a-f]+:[ ]+0ff0000f[ ]+fence
[ ]+[0-9a-f]+:[ ]+8330000f[ ]+fence\.tso
[ ]+[0-9a-f]+:[ ]+0100000f[ ]+fence[ ]+w,none
[ ]+[0-9a-f]+:[ ]+0cf00f8f[ ]+fence[ ]+io,iorw
[ ]+[0-9a-f]+:[ ]+0fcf800f[ ]+fence[ ]+iorw,io
[ ]+[0-9a-f]+:[ ]+83300f8f[ ]+fence\.tso
[ ]+[0-9a-f]+:[ ]+833f800f[ ]+fence\.tso
[ ]+[0-9a-f]+:[ ]+8ff0000f[ ]+fence[ ]+iorw,iorw
[ ]+[0-9a-f]+:[ ]+1330000f[ ]+fence[ ]+rw,rw
22 changes: 22 additions & 0 deletions gas/testsuite/gas/riscv/fence-dis-nonstd.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
target:
fence
fence.tso
# Standard encodings of fence and fence.tso
.insn i MISC_MEM, 0, x0, x0, 0x0ff
.insn i MISC_MEM, 0, x0, x0, 0x833-0x1000
# Standard encoding of pause
.insn i MISC_MEM, 0, x0, x0, 0x010
# Non-standard encodings (regular, either RD or RS1 are non-zero)
# Ignore unused bit fields.
.insn i MISC_MEM, 0, x31, x0, 0x0cf
.insn i MISC_MEM, 0, x0, x31, 0x0fc
# Non-standard encodings (TSO, either RD or RS1 are non-zero)
# Ignore unused bit fields for fence.tso.
.insn i MISC_MEM, 0, x31, x0, 0x833-0x1000
.insn i MISC_MEM, 0, x0, x31, 0x833-0x1000
# Non-standard encoding (TSO, pred and succ are not defined)
# Since fm+pred+succ is not defined, fallback to regular fence.
.insn i MISC_MEM, 0, x0, x0, 0x8ff-0x1000
# Non-standard encoding (fm is reserved)
# Fallback to regular fence.
.insn i MISC_MEM, 0, x0, x0, 0x133
3 changes: 0 additions & 3 deletions gas/testsuite/gas/riscv/rouding-fail.d

This file was deleted.

3 changes: 0 additions & 3 deletions gas/testsuite/gas/riscv/rouding-fail.s

This file was deleted.

13 changes: 13 additions & 0 deletions gas/testsuite/gas/riscv/rounding-dis-widening-noalias.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#as: -march=rv32ifd
#source: rounding-dis-widening.s
#objdump: -dr -M no-aliases

.*:[ ]+file format .*


Disassembly of section .text:

0+000 <target>:
[ ]+[0-9a-f]+:[ ]+420100d3[ ]+fcvt\.d\.s[ ]+ft1,ft2
[ ]+[0-9a-f]+:[ ]+420100d3[ ]+fcvt\.d\.s[ ]+ft1,ft2
[ ]+[0-9a-f]+:[ ]+420170d3[ ]+fcvt\.d\.s[ ]+ft1,ft2,dyn
13 changes: 13 additions & 0 deletions gas/testsuite/gas/riscv/rounding-dis-widening.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#as: -march=rv32ifd
#source: rounding-dis-widening.s
#objdump: -dr

.*:[ ]+file format .*


Disassembly of section .text:

0+000 <target>:
[ ]+[0-9a-f]+:[ ]+420100d3[ ]+fcvt\.d\.s[ ]+ft1,ft2
[ ]+[0-9a-f]+:[ ]+420100d3[ ]+fcvt\.d\.s[ ]+ft1,ft2
[ ]+[0-9a-f]+:[ ]+420170d3[ ]+fcvt\.d\.s[ ]+ft1,ft2
8 changes: 8 additions & 0 deletions gas/testsuite/gas/riscv/rounding-dis-widening.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
target:
fcvt.d.s ft1, ft2
# Standard encoding:
# - 2nd operand is the rounding mode (RNE [0b000] is preferred).
# - 6th operand (additional function) is zero for FCVT.D.S.
.insn r OP_FP, 0x0, 0x21, ft1, ft2, f0
# Non-standard encoding
.insn r OP_FP, 0x7, 0x21, ft1, ft2, f0
3 changes: 3 additions & 0 deletions gas/testsuite/gas/riscv/rounding-fail-invalid.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#as: -march=rv32ifd
#source: rounding-fail-invalid.s
#error_output: rounding-fail-invalid.l
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.*: Assembler messages:
.*: Error: illegal operands `fadd.s fa1,fa1,fa1,'
.*: Error: illegal operands `fadd.d fa1,fa1,fa1,'
.*: Error: illegal operands `fadd.s fa1,fa1,fa1,unknown'
.*: Error: illegal operands `fadd.d fa1,fa1,fa1,unknown'
5 changes: 5 additions & 0 deletions gas/testsuite/gas/riscv/rounding-fail-invalid.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
target:
fadd.s fa1,fa1,fa1,
fadd.d fa1,fa1,fa1,
fadd.s fa1,fa1,fa1,unknown
fadd.d fa1,fa1,fa1,unknown
3 changes: 3 additions & 0 deletions gas/testsuite/gas/riscv/rounding-fail-widening.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#as: -march=rv32ifdq_zfh
#source: rounding-fail-widening.s
#error_output: rounding-fail-widening.l
12 changes: 12 additions & 0 deletions gas/testsuite/gas/riscv/rounding-fail-widening.l
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.*: Assembler messages:
.*: Error: rounding mode cannot be specified on widening conversion
.*: Error: rounding mode cannot be specified on widening conversion
.*: Error: rounding mode cannot be specified on widening conversion
.*: Error: rounding mode cannot be specified on widening conversion
.*: Error: rounding mode cannot be specified on widening conversion
.*: Error: rounding mode cannot be specified on widening conversion
.*: Error: rounding mode cannot be specified on widening conversion
.*: Error: rounding mode cannot be specified on widening conversion
.*: Error: rounding mode cannot be specified on widening conversion
.*: Error: rounding mode cannot be specified on widening conversion
.*: Error: illegal operands `fcvt\.q\.wu ft1,t0,unknown'
15 changes: 15 additions & 0 deletions gas/testsuite/gas/riscv/rounding-fail-widening.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
target:
# Whitespaces before "dyn" are intended to test different
# coding styles and whitespace handling.
fcvt.s.h ft1,ft2 , dyn
fcvt.d.h ft1,ft2 , dyn
fcvt.q.h ft1,ft2, dyn
fcvt.d.s ft1,ft2,dyn
fcvt.q.s ft1,ft2,dyn
fcvt.q.d ft1,ft2,dyn
fcvt.d.w ft1,t0,dyn
fcvt.d.wu ft1,t0,dyn
fcvt.q.w ft1,t0,dyn
fcvt.q.wu ft1,t0,dyn
# Different error message because of an invalid rounding mode
fcvt.q.wu ft1,t0,unknown
15 changes: 15 additions & 0 deletions gas/testsuite/gas/riscv/rounding-fcvt.q.l-noalias.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#as: -march=rv64ifdq
#source: rounding-fcvt.q.l.s
#warning_output: rounding-fcvt.q.l.l
#objdump: -dr -M no-aliases

.*:[ ]+file format .*


Disassembly of section .text:

0+000 <target>:
[ ]+[0-9a-f]+:[ ]+d62280d3[ ]+fcvt\.q\.l[ ]+ft1,t0
[ ]+[0-9a-f]+:[ ]+d622f0d3[ ]+fcvt\.q\.l[ ]+ft1,t0,dyn
[ ]+[0-9a-f]+:[ ]+d63280d3[ ]+fcvt\.q\.lu[ ]+ft1,t0
[ ]+[0-9a-f]+:[ ]+d632f0d3[ ]+fcvt\.q\.lu[ ]+ft1,t0,dyn
15 changes: 15 additions & 0 deletions gas/testsuite/gas/riscv/rounding-fcvt.q.l.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#as: -march=rv64ifdq
#source: rounding-fcvt.q.l.s
#warning_output: rounding-fcvt.q.l.l
#objdump: -dr

.*:[ ]+file format .*


Disassembly of section .text:

0+000 <target>:
[ ]+[0-9a-f]+:[ ]+d62280d3[ ]+fcvt\.q\.l[ ]+ft1,t0
[ ]+[0-9a-f]+:[ ]+d622f0d3[ ]+fcvt\.q\.l[ ]+ft1,t0
[ ]+[0-9a-f]+:[ ]+d63280d3[ ]+fcvt\.q\.lu[ ]+ft1,t0
[ ]+[0-9a-f]+:[ ]+d632f0d3[ ]+fcvt\.q\.lu[ ]+ft1,t0
3 changes: 3 additions & 0 deletions gas/testsuite/gas/riscv/rounding-fcvt.q.l.l
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.*: Assembler messages:
.*: Warning: specifying a rounding mode is strongly discourged on widening conversion
.*: Warning: specifying a rounding mode is strongly discourged on widening conversion
5 changes: 5 additions & 0 deletions gas/testsuite/gas/riscv/rounding-fcvt.q.l.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
target:
fcvt.q.l ft1,t0
fcvt.q.l ft1,t0,dyn
fcvt.q.lu ft1,t0
fcvt.q.lu ft1,t0,dyn
15 changes: 15 additions & 0 deletions gas/testsuite/gas/riscv/zifencei-dis-nonstd.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#as: -march=rv32i_zifencei
#source: zifencei-dis-nonstd.s
#objdump: -dr

.*:[ ]+file format .*


Disassembly of section .text:

0+000 <target>:
[ ]+[0-9a-f]+:[ ]+0000100f[ ]+fence\.i
[ ]+[0-9a-f]+:[ ]+0000100f[ ]+fence\.i
[ ]+[0-9a-f]+:[ ]+00001f8f[ ]+fence\.i
[ ]+[0-9a-f]+:[ ]+000f900f[ ]+fence\.i
[ ]+[0-9a-f]+:[ ]+fff0100f[ ]+fence\.i
8 changes: 8 additions & 0 deletions gas/testsuite/gas/riscv/zifencei-dis-nonstd.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
target:
fence.i
# Standard encoding of fence.i
.insn i MISC_MEM, 1, x0, x0, 0
# Following are non-standard encodings
.insn i MISC_MEM, 1, x31, x0, 0
.insn i MISC_MEM, 1, x0, x31, 0
.insn i MISC_MEM, 1, x0, x0, -1
2 changes: 2 additions & 0 deletions include/opcode/riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@ static inline unsigned int riscv_insn_length (insn_t insn)
#define OP_SH_AQ 26
#define OP_MASK_RL 0x1
#define OP_SH_RL 25
#define OP_MASK_FM 0xfU
#define OP_SH_FM 28

#define OP_MASK_CSR 0xfffU
#define OP_SH_CSR 20
Expand Down
Loading