Skip to content

Commit 2c13c79

Browse files
committed
RISC-V: Rounding mode on widening instructions
This commit adds support for rounding modes on widening instructions to the assembler/disassembler. On the disassembler, non-default rounding mode is displayed when "no-aliases" option is given or the rounding mode itself is invalid. On the assembler, specifying such rounding modes is prohibited unless we have supported in the past. gas/ChangeLog: * config/tc-riscv.c (validate_riscv_insn): Add rounding mode support to widening instructions. (riscv_ip): Likewise. * testsuite/gas/riscv/rounding-dis-widening.d: New disasm test. * testsuite/gas/riscv/rounding-dis-widening.s: Likewise. * testsuite/gas/riscv/rounding-dis-widening-noalias.d: Likewise. * testsuite/gas/riscv/rounding-fail.d: Add testcases for widening instructions. * testsuite/gas/riscv/rounding-fail.l: Likewise. * testsuite/gas/riscv/rounding-fail.s: Likewise. * testsuite/gas/riscv/rounding-fcvt.q.l.d: New test. * testsuite/gas/riscv/rounding-fcvt.q.l.l: Likewise. * testsuite/gas/riscv/rounding-fcvt.q.l.s: Likewise. * testsuite/gas/riscv/rounding-fcvt.q.l-noalias.d: Likewise. opcodes/ChangeLog: * riscv-dis.c (print_insn_args): Add rounding mode support to widening instructions. * riscv-opc.c (riscv_opcodes): Use new operand types. Idea-by: Tsukasa OI <[email protected]> Idea-by: S Pawan Kumar <[email protected]>
1 parent 3710782 commit 2c13c79

13 files changed

+177
-15
lines changed

gas/config/tc-riscv.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,6 +1396,15 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
13961396
goto unknown_validate_operand;
13971397
}
13981398
break;
1399+
case 'f':
1400+
switch (*++oparg)
1401+
{
1402+
case 'M': /* Fall through. */
1403+
case 'm': USE_BITS (OP_MASK_RM, OP_SH_RM); break;
1404+
default:
1405+
goto unknown_validate_operand;
1406+
}
1407+
break;
13991408
default:
14001409
goto unknown_validate_operand;
14011410
}
@@ -3442,6 +3451,40 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
34423451
goto unknown_riscv_ip_operand;
34433452
}
34443453
break;
3454+
case 'f':
3455+
switch (*++oparg)
3456+
{
3457+
case 'M':
3458+
case 'm':
3459+
/* Optional rounding mode (widening conversion)
3460+
'M': operand either disallowed or not recommended
3461+
(considered to be non-useful to normal software).
3462+
'm': operand allowed for compatibility reasons
3463+
(display a warning instead). */
3464+
if (*asarg == '\0')
3465+
{
3466+
INSERT_OPERAND (RM, *ip, 0);
3467+
continue;
3468+
}
3469+
else if (*asarg == ',' && asarg++
3470+
&& arg_lookup (&asarg, riscv_rm,
3471+
ARRAY_SIZE (riscv_rm), &regno))
3472+
{
3473+
INSERT_OPERAND (RM, *ip, regno);
3474+
if (*oparg == 'M')
3475+
as_bad (_ ("rounding mode cannot be specified "
3476+
"on widening conversion"));
3477+
else
3478+
as_warn (
3479+
_ ("specifying a rounding mode is strongly "
3480+
"discourged on widening conversion"));
3481+
continue;
3482+
}
3483+
break;
3484+
default:
3485+
goto unknown_riscv_ip_operand;
3486+
}
3487+
break;
34453488
default:
34463489
goto unknown_riscv_ip_operand;
34473490
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#as: -march=rv32ifd
2+
#source: rounding-dis-widening.s
3+
#objdump: -d -M no-aliases
4+
5+
.*:[ ]+file format .*
6+
7+
8+
Disassembly of section .text:
9+
10+
0+000 <target>:
11+
[ ]+[0-9a-f]+:[ ]+420100d3[ ]+fcvt\.d\.s[ ]+ft1,ft2
12+
[ ]+[0-9a-f]+:[ ]+420100d3[ ]+fcvt\.d\.s[ ]+ft1,ft2
13+
[ ]+[0-9a-f]+:[ ]+420170d3[ ]+fcvt\.d\.s[ ]+ft1,ft2,dyn
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#as: -march=rv32ifd
2+
#source: rounding-dis-widening.s
3+
#objdump: -d
4+
5+
.*:[ ]+file format .*
6+
7+
8+
Disassembly of section .text:
9+
10+
0+000 <target>:
11+
[ ]+[0-9a-f]+:[ ]+420100d3[ ]+fcvt\.d\.s[ ]+ft1,ft2
12+
[ ]+[0-9a-f]+:[ ]+420100d3[ ]+fcvt\.d\.s[ ]+ft1,ft2
13+
[ ]+[0-9a-f]+:[ ]+420170d3[ ]+fcvt\.d\.s[ ]+ft1,ft2
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
target:
2+
fcvt.d.s ft1, ft2
3+
# Standard encoding:
4+
# - 2nd operand is the rounding mode (RNE [0b000] is preferred).
5+
# - 6th operand (additional function) is zero for FCVT.D.S.
6+
.insn r OP_FP, 0x0, 0x21, ft1, ft2, f0
7+
# Non-standard encoding
8+
.insn r OP_FP, 0x7, 0x21, ft1, ft2, f0
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
#as: -march=rv32ifd
1+
#as: -march=rv32ifdq_zfh
22
#source: rounding-fail.s
33
#error_output: rounding-fail.l

gas/testsuite/gas/riscv/rounding-fail.l

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,14 @@
33
.*: Error: illegal operands `fadd.d fa1,fa1,fa1,'
44
.*: Error: illegal operands `fadd.s fa1,fa1,fa1,unknown'
55
.*: Error: illegal operands `fadd.d fa1,fa1,fa1,unknown'
6+
.*: Error: rounding mode cannot be specified on widening conversion
7+
.*: Error: rounding mode cannot be specified on widening conversion
8+
.*: Error: rounding mode cannot be specified on widening conversion
9+
.*: Error: rounding mode cannot be specified on widening conversion
10+
.*: Error: rounding mode cannot be specified on widening conversion
11+
.*: Error: rounding mode cannot be specified on widening conversion
12+
.*: Error: rounding mode cannot be specified on widening conversion
13+
.*: Error: rounding mode cannot be specified on widening conversion
14+
.*: Error: rounding mode cannot be specified on widening conversion
15+
.*: Error: rounding mode cannot be specified on widening conversion
16+
.*: Error: illegal operands `fcvt\.q\.wu ft1,t0,unknown'

gas/testsuite/gas/riscv/rounding-fail.s

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,19 @@ target:
44
fadd.d fa1,fa1,fa1,
55
fadd.s fa1,fa1,fa1,unknown
66
fadd.d fa1,fa1,fa1,unknown
7+
8+
# Rounding mode cannot be specified on widening conversion
9+
# unless we have supported in the past.
10+
fcvt.s.h ft1,ft2,dyn
11+
fcvt.d.h ft1,ft2,dyn
12+
fcvt.q.h ft1,ft2,dyn
13+
fcvt.d.s ft1,ft2,dyn
14+
fcvt.q.s ft1,ft2,dyn
15+
fcvt.q.d ft1,ft2,dyn
16+
fcvt.d.w ft1,t0,dyn
17+
fcvt.d.wu ft1,t0,dyn
18+
fcvt.q.w ft1,t0,dyn
19+
fcvt.q.wu ft1,t0,dyn
20+
21+
# Different error message because of an invalid rounding mode
22+
fcvt.q.wu ft1,t0,unknown
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#as: -march=rv64ifdq
2+
#source: rounding-fcvt.q.l.s
3+
#warning_output: rounding-fcvt.q.l.l
4+
#objdump: -d -M no-aliases
5+
6+
.*:[ ]+file format .*
7+
8+
9+
Disassembly of section .text:
10+
11+
0+000 <target>:
12+
[ ]+[0-9a-f]+:[ ]+d62280d3[ ]+fcvt\.q\.l[ ]+ft1,t0
13+
[ ]+[0-9a-f]+:[ ]+d622f0d3[ ]+fcvt\.q\.l[ ]+ft1,t0,dyn
14+
[ ]+[0-9a-f]+:[ ]+d63280d3[ ]+fcvt\.q\.lu[ ]+ft1,t0
15+
[ ]+[0-9a-f]+:[ ]+d632f0d3[ ]+fcvt\.q\.lu[ ]+ft1,t0,dyn
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#as: -march=rv64ifdq
2+
#source: rounding-fcvt.q.l.s
3+
#warning_output: rounding-fcvt.q.l.l
4+
#objdump: -d
5+
6+
.*:[ ]+file format .*
7+
8+
9+
Disassembly of section .text:
10+
11+
0+000 <target>:
12+
[ ]+[0-9a-f]+:[ ]+d62280d3[ ]+fcvt\.q\.l[ ]+ft1,t0
13+
[ ]+[0-9a-f]+:[ ]+d622f0d3[ ]+fcvt\.q\.l[ ]+ft1,t0
14+
[ ]+[0-9a-f]+:[ ]+d63280d3[ ]+fcvt\.q\.lu[ ]+ft1,t0
15+
[ ]+[0-9a-f]+:[ ]+d632f0d3[ ]+fcvt\.q\.lu[ ]+ft1,t0
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.*: Assembler messages:
2+
.*: Warning: specifying a rounding mode is strongly discourged on widening conversion
3+
.*: Warning: specifying a rounding mode is strongly discourged on widening conversion
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
target:
2+
fcvt.q.l ft1,t0
3+
fcvt.q.l ft1,t0,dyn
4+
fcvt.q.lu ft1,t0
5+
fcvt.q.lu ft1,t0,dyn

opcodes/riscv-dis.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,27 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
592592
goto undefined_modifier;
593593
}
594594
break;
595+
case 'f':
596+
switch (*++oparg)
597+
{
598+
case 'M': /* Fall through. */
599+
case 'm':
600+
/* Optional rounding mode (widening conversion)
601+
which defaults to RNE (0b000).
602+
Display non-default rounding mode if:
603+
1. rounding mode is invalid or
604+
2. 'no-aliases' option is specified. */
605+
if (EXTRACT_OPERAND (RM, l) == 0
606+
|| (!no_aliases && riscv_rm[EXTRACT_OPERAND (RM, l)]))
607+
break;
608+
print (info->stream, dis_style_text, ",");
609+
arg_print (info, EXTRACT_OPERAND (RM, l), riscv_rm,
610+
ARRAY_SIZE (riscv_rm));
611+
break;
612+
default:
613+
goto undefined_modifier;
614+
}
615+
break;
595616
default:
596617
goto undefined_modifier;
597618
}
@@ -640,6 +661,7 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
640661
}
641662
}
642663
break;
664+
643665
default:
644666
undefined_modifier:
645667
/* xgettext:c-format */

opcodes/riscv-opc.c

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -659,9 +659,9 @@ const struct riscv_opcode riscv_opcodes[] =
659659
{"fcvt.h.w", 0, INSN_CLASS_ZFH_INX, "D,s,m", MATCH_FCVT_H_W, MASK_FCVT_H_W, match_opcode, 0 },
660660
{"fcvt.h.wu", 0, INSN_CLASS_ZFH_INX, "D,s", MATCH_FCVT_H_WU|MASK_RM, MASK_FCVT_H_WU|MASK_RM, match_opcode, 0 },
661661
{"fcvt.h.wu", 0, INSN_CLASS_ZFH_INX, "D,s,m", MATCH_FCVT_H_WU, MASK_FCVT_H_WU, match_opcode, 0 },
662-
{"fcvt.s.h", 0, INSN_CLASS_ZFHMIN_INX, "D,S", MATCH_FCVT_S_H, MASK_FCVT_S_H|MASK_RM, match_opcode, 0 },
663-
{"fcvt.d.h", 0, INSN_CLASS_ZFHMIN_AND_D_INX, "D,S", MATCH_FCVT_D_H, MASK_FCVT_D_H|MASK_RM, match_opcode, 0 },
664-
{"fcvt.q.h", 0, INSN_CLASS_ZFHMIN_AND_Q_INX, "D,S", MATCH_FCVT_Q_H, MASK_FCVT_Q_H|MASK_RM, match_opcode, 0 },
662+
{"fcvt.s.h", 0, INSN_CLASS_ZFHMIN_INX, "D,SWfM", MATCH_FCVT_S_H, MASK_FCVT_S_H, match_opcode, 0 },
663+
{"fcvt.d.h", 0, INSN_CLASS_ZFHMIN_AND_D_INX, "D,SWfM", MATCH_FCVT_D_H, MASK_FCVT_D_H, match_opcode, 0 },
664+
{"fcvt.q.h", 0, INSN_CLASS_ZFHMIN_AND_Q_INX, "D,SWfM", MATCH_FCVT_Q_H, MASK_FCVT_Q_H, match_opcode, 0 },
665665
{"fcvt.h.s", 0, INSN_CLASS_ZFHMIN_INX, "D,S", MATCH_FCVT_H_S|MASK_RM, MASK_FCVT_H_S|MASK_RM, match_opcode, 0 },
666666
{"fcvt.h.s", 0, INSN_CLASS_ZFHMIN_INX, "D,S,m", MATCH_FCVT_H_S, MASK_FCVT_H_S, match_opcode, 0 },
667667
{"fcvt.h.d", 0, INSN_CLASS_ZFHMIN_AND_D_INX, "D,S", MATCH_FCVT_H_D|MASK_RM, MASK_FCVT_H_D|MASK_RM, match_opcode, 0 },
@@ -800,9 +800,9 @@ const struct riscv_opcode riscv_opcodes[] =
800800
{"fcvt.w.d", 0, INSN_CLASS_D_INX, "d,S,m", MATCH_FCVT_W_D, MASK_FCVT_W_D, match_opcode, 0 },
801801
{"fcvt.wu.d", 0, INSN_CLASS_D_INX, "d,S", MATCH_FCVT_WU_D|MASK_RM, MASK_FCVT_WU_D|MASK_RM, match_opcode, 0 },
802802
{"fcvt.wu.d", 0, INSN_CLASS_D_INX, "d,S,m", MATCH_FCVT_WU_D, MASK_FCVT_WU_D, match_opcode, 0 },
803-
{"fcvt.d.w", 0, INSN_CLASS_D_INX, "D,s", MATCH_FCVT_D_W, MASK_FCVT_D_W|MASK_RM, match_opcode, 0 },
804-
{"fcvt.d.wu", 0, INSN_CLASS_D_INX, "D,s", MATCH_FCVT_D_WU, MASK_FCVT_D_WU|MASK_RM, match_opcode, 0 },
805-
{"fcvt.d.s", 0, INSN_CLASS_D_INX, "D,S", MATCH_FCVT_D_S, MASK_FCVT_D_S|MASK_RM, match_opcode, 0 },
803+
{"fcvt.d.w", 0, INSN_CLASS_D_INX, "D,sWfM", MATCH_FCVT_D_W, MASK_FCVT_D_W, match_opcode, 0 },
804+
{"fcvt.d.wu", 0, INSN_CLASS_D_INX, "D,sWfM", MATCH_FCVT_D_WU, MASK_FCVT_D_WU, match_opcode, 0 },
805+
{"fcvt.d.s", 0, INSN_CLASS_D_INX, "D,SWfM", MATCH_FCVT_D_S, MASK_FCVT_D_S, match_opcode, 0 },
806806
{"fcvt.s.d", 0, INSN_CLASS_D_INX, "D,S", MATCH_FCVT_S_D|MASK_RM, MASK_FCVT_S_D|MASK_RM, match_opcode, 0 },
807807
{"fcvt.s.d", 0, INSN_CLASS_D_INX, "D,S,m", MATCH_FCVT_S_D, MASK_FCVT_S_D, match_opcode, 0 },
808808
{"fclass.d", 0, INSN_CLASS_D_INX, "d,S", MATCH_FCLASS_D, MASK_FCLASS_D, match_opcode, 0 },
@@ -857,10 +857,10 @@ const struct riscv_opcode riscv_opcodes[] =
857857
{"fcvt.w.q", 0, INSN_CLASS_Q_INX, "d,S,m", MATCH_FCVT_W_Q, MASK_FCVT_W_Q, match_opcode, 0 },
858858
{"fcvt.wu.q", 0, INSN_CLASS_Q_INX, "d,S", MATCH_FCVT_WU_Q|MASK_RM, MASK_FCVT_WU_Q|MASK_RM, match_opcode, 0 },
859859
{"fcvt.wu.q", 0, INSN_CLASS_Q_INX, "d,S,m", MATCH_FCVT_WU_Q, MASK_FCVT_WU_Q, match_opcode, 0 },
860-
{"fcvt.q.w", 0, INSN_CLASS_Q_INX, "D,s", MATCH_FCVT_Q_W, MASK_FCVT_Q_W|MASK_RM, match_opcode, 0 },
861-
{"fcvt.q.wu", 0, INSN_CLASS_Q_INX, "D,s", MATCH_FCVT_Q_WU, MASK_FCVT_Q_WU|MASK_RM, match_opcode, 0 },
862-
{"fcvt.q.s", 0, INSN_CLASS_Q_INX, "D,S", MATCH_FCVT_Q_S, MASK_FCVT_Q_S|MASK_RM, match_opcode, 0 },
863-
{"fcvt.q.d", 0, INSN_CLASS_Q_INX, "D,S", MATCH_FCVT_Q_D, MASK_FCVT_Q_D|MASK_RM, match_opcode, 0 },
860+
{"fcvt.q.w", 0, INSN_CLASS_Q_INX, "D,sWfM", MATCH_FCVT_Q_W, MASK_FCVT_Q_W, match_opcode, 0 },
861+
{"fcvt.q.wu", 0, INSN_CLASS_Q_INX, "D,sWfM", MATCH_FCVT_Q_WU, MASK_FCVT_Q_WU, match_opcode, 0 },
862+
{"fcvt.q.s", 0, INSN_CLASS_Q_INX, "D,SWfM", MATCH_FCVT_Q_S, MASK_FCVT_Q_S, match_opcode, 0 },
863+
{"fcvt.q.d", 0, INSN_CLASS_Q_INX, "D,SWfM", MATCH_FCVT_Q_D, MASK_FCVT_Q_D, match_opcode, 0 },
864864
{"fcvt.s.q", 0, INSN_CLASS_Q_INX, "D,S", MATCH_FCVT_S_Q|MASK_RM, MASK_FCVT_S_Q|MASK_RM, match_opcode, 0 },
865865
{"fcvt.s.q", 0, INSN_CLASS_Q_INX, "D,S,m", MATCH_FCVT_S_Q, MASK_FCVT_S_Q, match_opcode, 0 },
866866
{"fcvt.d.q", 0, INSN_CLASS_Q_INX, "D,S", MATCH_FCVT_D_Q|MASK_RM, MASK_FCVT_D_Q|MASK_RM, match_opcode, 0 },
@@ -875,10 +875,8 @@ const struct riscv_opcode riscv_opcodes[] =
875875
{"fcvt.l.q", 64, INSN_CLASS_Q_INX, "d,S,m", MATCH_FCVT_L_Q, MASK_FCVT_L_Q, match_opcode, 0 },
876876
{"fcvt.lu.q", 64, INSN_CLASS_Q_INX, "d,S", MATCH_FCVT_LU_Q|MASK_RM, MASK_FCVT_LU_Q|MASK_RM, match_opcode, 0 },
877877
{"fcvt.lu.q", 64, INSN_CLASS_Q_INX, "d,S,m", MATCH_FCVT_LU_Q, MASK_FCVT_LU_Q, match_opcode, 0 },
878-
{"fcvt.q.l", 64, INSN_CLASS_Q_INX, "D,s", MATCH_FCVT_Q_L, MASK_FCVT_Q_L|MASK_RM, match_opcode, 0 },
879-
{"fcvt.q.l", 64, INSN_CLASS_Q_INX, "D,s,m", MATCH_FCVT_Q_L, MASK_FCVT_Q_L, match_opcode, 0 },
880-
{"fcvt.q.lu", 64, INSN_CLASS_Q_INX, "D,s", MATCH_FCVT_Q_LU, MASK_FCVT_Q_LU|MASK_RM, match_opcode, 0 },
881-
{"fcvt.q.lu", 64, INSN_CLASS_Q_INX, "D,s,m", MATCH_FCVT_Q_LU, MASK_FCVT_Q_LU, match_opcode, 0 },
878+
{"fcvt.q.l", 64, INSN_CLASS_Q_INX, "D,sWfm", MATCH_FCVT_Q_L, MASK_FCVT_Q_L, match_opcode, 0 },
879+
{"fcvt.q.lu", 64, INSN_CLASS_Q_INX, "D,sWfm", MATCH_FCVT_Q_LU, MASK_FCVT_Q_LU, match_opcode, 0 },
882880

883881
/* Compressed instructions. */
884882
{"c.unimp", 0, INSN_CLASS_C, "", 0, 0xffffU, match_opcode, 0 },

0 commit comments

Comments
 (0)