RISC-V/gas: allow generating up to 176-bit instructions with .insn

For the time being simply utilize O_big to avoid widening other fields,
bypassing append_insn() etc.
This commit is contained in:
Jan Beulich 2022-10-04 09:46:11 +02:00
parent 8c07e983a2
commit bb996692bd
8 changed files with 85 additions and 10 deletions

View File

@ -3389,8 +3389,15 @@ riscv_ip_hardcode (char *str,
do
{
expression (imm_expr);
if (imm_expr->X_op != O_constant)
switch (imm_expr->X_op)
{
case O_constant:
values[num++] = (insn_t) imm_expr->X_add_number;
break;
case O_big:
values[num++] = generic_bignum[0];
break;
default:
/* The first value isn't constant, so it should be
.insn <type> <operands>. We have been parsed it
in the riscv_ip. */
@ -3398,9 +3405,8 @@ riscv_ip_hardcode (char *str,
return error;
return _("values must be constant");
}
values[num++] = (insn_t) imm_expr->X_add_number;
}
while (*input_line_pointer++ == ',' && num < 2);
while (*input_line_pointer++ == ',' && num < 2 && imm_expr->X_op != O_big);
input_line_pointer--;
if (*input_line_pointer != '\0')
@ -3410,8 +3416,22 @@ riscv_ip_hardcode (char *str,
insn->match = values[num - 1];
create_insn (ip, insn);
unsigned int bytes = riscv_insn_length (insn->match);
if ((bytes < sizeof(values[0]) && values[num - 1] >> (8 * bytes) != 0)
|| (num == 2 && values[0] != bytes))
if (num == 2 && values[0] != bytes)
return _("value conflicts with instruction length");
if (imm_expr->X_op == O_big)
{
if (bytes != imm_expr->X_add_number * CHARS_PER_LITTLENUM)
return _("value conflicts with instruction length");
char *f = frag_more (bytes);
for (num = 0; num < imm_expr->X_add_number; ++num)
number_to_chars_littleendian (f + num * CHARS_PER_LITTLENUM,
generic_bignum[num], CHARS_PER_LITTLENUM);
return NULL;
}
if (bytes < sizeof(values[0]) && values[num - 1] >> (8 * bytes) != 0)
return _("value conflicts with instruction length");
return NULL;
@ -4476,7 +4496,7 @@ s_riscv_insn (int x ATTRIBUTE_UNUSED)
else
as_bad ("%s `%s'", error.msg, error.statement);
}
else
else if (imm_expr.X_op != O_big)
{
gas_assert (insn.insn_mo->pinfo != INSN_MACRO);
append_insn (&insn, &imm_expr, imm_reloc);

View File

@ -65,8 +65,14 @@ insn.s +60 +0xac.*
insn.s +61 +0xb0.*
insn.s +62 +0xb6.*
insn.s +63 +0xbe.*
insn.s +64 +0xc0.*
insn.s +65 +0xc4.*
insn.s +66 +0xca.*
insn.s +- +0xd2
insn.s +64 +0xc8.*
insn.s +65 +0xd4.*
insn.s +66 +0xea.*
insn.s +67 +0xec.*
insn.s +68 +0xf0.*
insn.s +69 +0xf6.*
insn.s +70 +0xfe.*
insn.s +71 +0x108.*
insn.s +72 +0x114.*
insn.s +- +0x12a
#pass

View File

@ -5,3 +5,13 @@
.*Error: unrecognized values `0x4,0x5,0x6'
.*Error: value conflicts with instruction length `0x4,0x0001'
.*Error: value conflicts with instruction length `0x2,0x00000013'
.*Error: value conflicts with instruction length `0x10+1f'
.*Error: value conflicts with instruction length `6,0x10+1f'
.*Error: value conflicts with instruction length `0x10+3f'
.*Error: value conflicts with instruction length `8,0x10+3f'
.*Error: value conflicts with instruction length `0x10+7f'
.*Error: value conflicts with instruction length `10,0x10+7f'
.*Error: value conflicts with instruction length `0x10+107f'
.*Error: value conflicts with instruction length `12,0x10+107f'
.*Error: value conflicts with instruction length `0x10+607f'
.*Error: value conflicts with instruction length `22,0x10+607f'

View File

@ -4,3 +4,13 @@
.insn 0x4, 0x5, 0x6
.insn 0x4, 0x0001
.insn 0x2, 0x00000013
.insn 0x100000000001f
.insn 6, 0x100000000001f
.insn 0x1000000000000003f
.insn 8, 0x1000000000000003f
.insn 0x10000000000000000007f
.insn 10, 0x10000000000000000007f
.insn 0x100000000000000000000107f
.insn 12, 0x100000000000000000000107f
.insn 0x10000000000000000000000000000000000000000607f
.insn 22, 0x10000000000000000000000000000000000000000607f

View File

@ -63,7 +63,13 @@ Disassembly of section .text:
[^:]+:[ ]+00000013[ ]+addi[ ]+zero,zero,0
[^:]+:[ ]+001f 0000 0000[ ].*
[^:]+:[ ]+0000003f 00000000[ ].*
[^:]+:[ ]+007f 0000 0000 0000 0000[ ]+[._a-z].*
[^:]+:[ ]+0000107f 00000000 00000000[ ]+[._a-z].*
[^:]+:[ ]+607f 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000[ ]+[._a-z].*
[^:]+:[ ]+0001[ ]+c\.addi[ ]+zero,0
[^:]+:[ ]+00000013[ ]+addi[ ]+zero,zero,0
[^:]+:[ ]+001f 0000 0000[ ].*
[^:]+:[ ]+0000003f 00000000[ ].*
[^:]+:[ ]+007f 0000 0000 0000 0000[ ]+[._a-z].*
[^:]+:[ ]+0000107f 00000000 00000000[ ]+[._a-z].*
[^:]+:[ ]+607f 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000[ ]+[._a-z].*

View File

@ -74,7 +74,21 @@ Disassembly of section .text:
[^:]+:[ ]+00000013[ ]+nop
[^:]+:[ ]+001f 0000 0000[ ].*
[^:]+:[ ]+0000003f 00000000[ ].*
[^:]+:[ ]+007f 0000 0000 0000[ ]+[._a-z].*
[^:]+:[ ]+0000 ?
[^:]+:[ ]+0000107f 00000000[ ]+[._a-z].*
[^:]+:[ ]+00000000 ?
[^:]+:[ ]+607f 0000 0000 0000[ ]+[._a-z].*
[^:]+:[ ]+0000 0000 0000 0000 ?
[^:]+:[ ]+0000 0000 0000 ?
[^:]+:[ ]+0001[ ]+nop
[^:]+:[ ]+00000013[ ]+nop
[^:]+:[ ]+001f 0000 0000[ ].*
[^:]+:[ ]+0000003f 00000000[ ].*
[^:]+:[ ]+007f 0000 0000 0000[ ]+[._a-z].*
[^:]+:[ ]+0000 ?
[^:]+:[ ]+0000107f 00000000[ ]+[._a-z].*
[^:]+:[ ]+00000000 ?
[^:]+:[ ]+607f 0000 0000 0000[ ]+[._a-z].*
[^:]+:[ ]+0000 0000 0000 0000 ?
[^:]+:[ ]+0000 0000 0000 ?

View File

@ -60,7 +60,13 @@ target:
.insn 0x00000013
.insn 0x0000001f
.insn 0x0000003f
.insn 0x007f
.insn 0x107f
.insn 0x607f
.insn 0x2, 0x0001
.insn 0x4, 0x00000013
.insn 6, 0x0000001f
.insn 8, 0x0000003f
.insn 10, 0x007f
.insn 12, 0x107f
.insn 22, 0x607f

View File

@ -37,6 +37,9 @@ static inline unsigned int riscv_insn_length (insn_t insn)
return 6;
if ((insn & 0x7f) == 0x3f) /* 64-bit instructions. */
return 8;
/* 80- ... 176-bit instructions. */
if ((insn & 0x7f) == 0x7f && (insn & 0x7000) != 0x7000)
return 10 + ((insn >> 11) & 0xe);
/* Longer instructions not supported at the moment. */
return 2;
}