diff mbox

[v1,2/4] target-arm: A64: Handle blr lr

Message ID 1398926097-28097-3-git-send-email-edgar.iglesias@gmail.com
State New
Headers show

Commit Message

Edgar E. Iglesias May 1, 2014, 6:34 a.m. UTC
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

For linked branches, updates to the link register happen
conceptually after the read of the branch target register.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 target-arm/translate-a64.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

Comments

Alex Bennée May 1, 2014, 9:02 a.m. UTC | #1
Edgar E. Iglesias <edgar.iglesias@gmail.com> writes:

> From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
>
> For linked branches, updates to the link register happen
> conceptually after the read of the branch target register.
>
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>

I'm trying to think of a case where this could actually cause a problem
but I can't. However from a clarity/correctness point of view it's
better.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  target-arm/translate-a64.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
> index d86b8ff..0862e54 100644
> --- a/target-arm/translate-a64.c
> +++ b/target-arm/translate-a64.c
> @@ -1507,8 +1507,10 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
>      switch (opc) {
>      case 0: /* BR */
>      case 2: /* RET */
> +        tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
>          break;
>      case 1: /* BLR */
> +        tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
>          tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
>          break;
>      case 4: /* ERET */
> @@ -1527,7 +1529,6 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
>          return;
>      }
>  
> -    tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
>      s->is_jmp = DISAS_JUMP;
>  }
Peter Maydell May 1, 2014, 9:31 a.m. UTC | #2
On 1 May 2014 10:02, Alex Bennée <alex.bennee@linaro.org> wrote:
>
> Edgar E. Iglesias <edgar.iglesias@gmail.com> writes:
>
>> From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
>>
>> For linked branches, updates to the link register happen
>> conceptually after the read of the branch target register.
>>
>> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
>
> I'm trying to think of a case where this could actually cause a problem
> but I can't. However from a clarity/correctness point of view it's
> better.

Well, we actually misexecute "BLR LR" otherwise, right?
That's probably not very common but there's no reason it
might not occur (eg call to a function pointer from a
function where LR has been saved on entry and is free
for use as a generic tempreg).

Cc: qemu-stable@nongnu.org

thanks
-- PMM
Edgar E. Iglesias May 1, 2014, 11:43 a.m. UTC | #3
On Thu, May 01, 2014 at 10:31:06AM +0100, Peter Maydell wrote:
> On 1 May 2014 10:02, Alex Bennée <alex.bennee@linaro.org> wrote:
> >
> > Edgar E. Iglesias <edgar.iglesias@gmail.com> writes:
> >
> >> From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
> >>
> >> For linked branches, updates to the link register happen
> >> conceptually after the read of the branch target register.
> >>
> >> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> >
> > I'm trying to think of a case where this could actually cause a problem
> > but I can't. However from a clarity/correctness point of view it's
> > better.
> 
> Well, we actually misexecute "BLR LR" otherwise, right?
> That's probably not very common but there's no reason it
> might not occur (eg call to a function pointer from a
> function where LR has been saved on entry and is free
> for use as a generic tempreg).

Right. For example, the kernel/kvm actually does this in
arch/arm64/kvm/hyp.S:773:       blr     lr

Thanks,
Edgar
Alex Bennée May 1, 2014, 1:55 p.m. UTC | #4
Edgar E. Iglesias <edgar.iglesias@gmail.com> writes:

> On Thu, May 01, 2014 at 10:31:06AM +0100, Peter Maydell wrote:
>> On 1 May 2014 10:02, Alex Bennée <alex.bennee@linaro.org> wrote:
>> >
>> > Edgar E. Iglesias <edgar.iglesias@gmail.com> writes:
>> >
>> >> From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
>> >>
>> >> For linked branches, updates to the link register happen
>> >> conceptually after the read of the branch target register.
>> >>
>> >> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
>> >
>> > I'm trying to think of a case where this could actually cause a problem
>> > but I can't. However from a clarity/correctness point of view it's
>> > better.
>> 
>> Well, we actually misexecute "BLR LR" otherwise, right?
>> That's probably not very common but there's no reason it
>> might not occur (eg call to a function pointer from a
>> function where LR has been saved on entry and is free
>> for use as a generic tempreg).
>
> Right. For example, the kernel/kvm actually does this in
> arch/arm64/kvm/hyp.S:773:       blr     lr

Of course, I see know ;-)
diff mbox

Patch

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index d86b8ff..0862e54 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1507,8 +1507,10 @@  static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
     switch (opc) {
     case 0: /* BR */
     case 2: /* RET */
+        tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
         break;
     case 1: /* BLR */
+        tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
         tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
         break;
     case 4: /* ERET */
@@ -1527,7 +1529,6 @@  static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
         return;
     }
 
-    tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
     s->is_jmp = DISAS_JUMP;
 }