2022-12-14 09:13:39

by Tiezhu Yang

[permalink] [raw]
Subject: [PATCH] LoongArch: Correct the definition of is_branch_ins()

The current definition of is_branch_ins() is not correct, it was
first introduced in commit 49aef111e2da ("LoongArch: Add prologue
unwinder support"), in fact, there exist three branch instruction
formats rather than only reg1i21_format.

Signed-off-by: Tiezhu Yang <[email protected]>
---
arch/loongarch/include/asm/inst.h | 27 +++++++++++++++++++++++++--
1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/arch/loongarch/include/asm/inst.h b/arch/loongarch/include/asm/inst.h
index c00e151..42be39be 100644
--- a/arch/loongarch/include/asm/inst.h
+++ b/arch/loongarch/include/asm/inst.h
@@ -329,8 +329,31 @@ static inline bool is_pc_ins(union loongarch_instruction *ip)

static inline bool is_branch_ins(union loongarch_instruction *ip)
{
- return ip->reg1i21_format.opcode >= beqz_op &&
- ip->reg1i21_format.opcode <= bgeu_op;
+ switch (ip->reg0i26_format.opcode) {
+ case b_op:
+ case bl_op:
+ return true;
+ }
+
+ switch (ip->reg1i21_format.opcode) {
+ case beqz_op:
+ case bnez_op:
+ case bceqz_op:
+ return true;
+ }
+
+ switch (ip->reg2i16_format.opcode) {
+ case jirl_op:
+ case beq_op:
+ case bne_op:
+ case blt_op:
+ case bge_op:
+ case bltu_op:
+ case bgeu_op:
+ return true;
+ }
+
+ return false;
}

static inline bool is_ra_save_ins(union loongarch_instruction *ip)
--
2.1.0


2022-12-16 03:45:18

by Jinyang He

[permalink] [raw]
Subject: Re: [PATCH] LoongArch: Correct the definition of is_branch_ins()

Hi, Tiezhu,


On 2022-12-14 16:30, Tiezhu Yang wrote:
> The current definition of is_branch_ins() is not correct,

But the branch instruction opcode only use the high 6 bits, [1]. That's
meaningless because it is the same as the original result. If we care
too much about the details of instruction format, we will lose a lot of
tricks on LoongArch instruction coding.

[1]
https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#table-of-instruction-encoding


> it was
> first introduced in commit 49aef111e2da ("LoongArch: Add prologue
> unwinder support"), in fact, there exist three branch instruction
> formats rather than only reg1i21_format.
>
> Signed-off-by: Tiezhu Yang <[email protected]>
> ---
> arch/loongarch/include/asm/inst.h | 27 +++++++++++++++++++++++++--
> 1 file changed, 25 insertions(+), 2 deletions(-)
>
> diff --git a/arch/loongarch/include/asm/inst.h b/arch/loongarch/include/asm/inst.h
> index c00e151..42be39be 100644
> --- a/arch/loongarch/include/asm/inst.h
> +++ b/arch/loongarch/include/asm/inst.h
> @@ -329,8 +329,31 @@ static inline bool is_pc_ins(union loongarch_instruction *ip)
>
> static inline bool is_branch_ins(union loongarch_instruction *ip)
> {
> - return ip->reg1i21_format.opcode >= beqz_op &&
> - ip->reg1i21_format.opcode <= bgeu_op;
> + switch (ip->reg0i26_format.opcode) {
> + case b_op:
> + case bl_op:
> + return true;
> + }
> +
> + switch (ip->reg1i21_format.opcode) {
> + case beqz_op:
> + case bnez_op:
> + case bceqz_op:
> + return true;
> + }
> +
> + switch (ip->reg2i16_format.opcode) {
> + case jirl_op:
> + case beq_op:
> + case bne_op:
> + case blt_op:
> + case bge_op:
> + case bltu_op:
> + case bgeu_op:
> + return true;
> + }
> +
> + return false;
> }
>
> static inline bool is_ra_save_ins(union loongarch_instruction *ip)

2022-12-16 06:47:09

by Tiezhu Yang

[permalink] [raw]
Subject: Re: [PATCH] LoongArch: Correct the definition of is_branch_ins()



On 12/16/2022 11:18 AM, Jinyang He wrote:
> Hi, Tiezhu,
>
>
> On 2022-12-14 16:30, Tiezhu Yang wrote:
>> The current definition of is_branch_ins() is not correct,
>
> But the branch instruction opcode only use the high 6 bits,

Yes, I noticed that, the logic result of current code is right,
but it seems a little strange (only consider reg1i21_format)
at the first glance, the initial aim of this patch is to make
it theoretically correct, maybe it is not the best change.

I think we can neglect the instruction formats and check the
high 6 bits instead, what do you think of the following change?

diff --git a/arch/loongarch/include/asm/inst.h
b/arch/loongarch/include/asm/inst.h
index c00e151..fd31752 100644
--- a/arch/loongarch/include/asm/inst.h
+++ b/arch/loongarch/include/asm/inst.h
@@ -329,8 +329,8 @@ static inline bool is_pc_ins(union
loongarch_instruction *ip)

static inline bool is_branch_ins(union loongarch_instruction *ip)
{
- return ip->reg1i21_format.opcode >= beqz_op &&
- ip->reg1i21_format.opcode <= bgeu_op;
+ return ((ip->word >> 26) & 0x3f) >= beqz_op &&
+ ((ip->word >> 26) & 0x3f) <= bgeu_op;
}

Thanks,
Tiezhu



2022-12-17 02:00:12

by Jinyang He

[permalink] [raw]
Subject: Re: [PATCH] LoongArch: Correct the definition of is_branch_ins()


On 2022-12-16 14:11, Tiezhu Yang wrote:
>
>
> On 12/16/2022 11:18 AM, Jinyang He wrote:
>> Hi, Tiezhu,
>>
>>
>> On 2022-12-14 16:30, Tiezhu Yang wrote:
>>> The current definition of is_branch_ins() is not correct,
>>
>> But the branch instruction opcode only use the high 6 bits,
>
> Yes, I noticed that, the logic result of current code is right,
> but it seems a little strange (only consider reg1i21_format)
> at the first glance, the initial aim of this patch is to make
> it theoretically correct, maybe it is not the best change.
>
> I think we can neglect the instruction formats and check the
> high 6 bits instead, what do you think of the following change?

We defined many instruction format because of variable-width opcode
field and parameter field. IMHO if there is no way to solve that problem
really, keeping original codes is better. That depends on the
maintainers, of course.


Thanks,

Jinyang


>
> diff --git a/arch/loongarch/include/asm/inst.h
> b/arch/loongarch/include/asm/inst.h
> index c00e151..fd31752 100644
> --- a/arch/loongarch/include/asm/inst.h
> +++ b/arch/loongarch/include/asm/inst.h
> @@ -329,8 +329,8 @@ static inline bool is_pc_ins(union
> loongarch_instruction *ip)
>
>  static inline bool is_branch_ins(union loongarch_instruction *ip)
>  {
> -       return ip->reg1i21_format.opcode >= beqz_op &&
> -               ip->reg1i21_format.opcode <= bgeu_op;
> +       return ((ip->word >> 26) & 0x3f) >= beqz_op &&
> +               ((ip->word >> 26) & 0x3f) <= bgeu_op;
>  }
>
> Thanks,
> Tiezhu
>
>
>