Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/aarch64/aarch64 implement properly branch_taken() a...



details:   https://anonhg.NetBSD.org/src/rev/fb787631ef5b
branches:  trunk
changeset: 319479:fb787631ef5b
user:      ryo <ryo%NetBSD.org@localhost>
date:      Thu May 31 09:37:16 2018 +0000

description:
implement properly branch_taken() and inst_unconditional_flow_transfer().

diffstat:

 sys/arch/aarch64/aarch64/db_interface.c |  77 ++++++++++++++++++++++++++++++--
 1 files changed, 71 insertions(+), 6 deletions(-)

diffs (105 lines):

diff -r 6ae9dc722cda -r fb787631ef5b sys/arch/aarch64/aarch64/db_interface.c
--- a/sys/arch/aarch64/aarch64/db_interface.c   Thu May 31 09:31:39 2018 +0000
+++ b/sys/arch/aarch64/aarch64/db_interface.c   Thu May 31 09:37:16 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: db_interface.c,v 1.2 2018/04/01 04:35:03 ryo Exp $ */
+/* $NetBSD: db_interface.c,v 1.3 2018/05/31 09:37:16 ryo Exp $ */
 
 /*
  * Copyright (c) 2017 Ryo Shimizu <ryo%nerv.org@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.2 2018/04/01 04:35:03 ryo Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.3 2018/05/31 09:37:16 ryo Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -128,17 +128,82 @@
        }
 }
 
+/*
+ * return register value of $X0..$X30, $SP or 0($XZR)
+ */
+static uint64_t
+db_fetch_reg(unsigned int reg, db_regs_t *regs, bool use_sp)
+{
+       if (reg >= 32)
+               panic("db_fetch_reg: botch");
+
+       if (reg == 31) {
+               /* $SP or $XZR */
+               return use_sp ? regs->tf_sp : 0;
+       }
+       return regs->tf_reg[reg];
+}
+
+static inline uint64_t
+SignExtend(int bitwidth, uint64_t imm, unsigned int multiply)
+{
+       const uint64_t signbit = (1 << (bitwidth - 1));
+       const uint64_t immmax = signbit << 1;
+
+       if (imm & signbit)
+               imm -= immmax;
+       return imm * multiply;
+}
+
 db_addr_t
 db_branch_taken(db_expr_t inst, db_addr_t pc, db_regs_t *regs)
 {
-       /* XXX */
-       return pc + 4;
+#define INSN_FMT_RN(insn)              (((insn) >> 5) & 0x1f)
+#define INSN_FMT_IMM26(insn)   ((insn) & 0x03ffffff)
+#define INSN_FMT_IMM19(insn)   (((insn) >> 5) & 0x7ffff)
+#define INSN_FMT_IMM14(insn)   (((insn) >> 5) & 0x3fff)
+
+       if (((inst & 0xfffffc1f) == 0xd65f0000) ||      /* ret xN */
+           ((inst & 0xfffffc1f) == 0xd63f0000) ||      /* blr xN */
+           ((inst & 0xfffffc1f) == 0xd61f0000)) {      /* br xN */
+               return db_fetch_reg(INSN_FMT_RN(inst), regs, false);
+       }
+
+       if (((inst & 0xfc000000) == 0x94000000) ||      /* bl imm */
+           ((inst & 0xfc000000) == 0x14000000)) {      /* b imm */
+               return SignExtend(26, INSN_FMT_IMM26(inst), 4) + pc;
+       }
+
+       if (((inst & 0xff000010) == 0x54000000) ||      /* b.cond */
+           ((inst & 0x7f000000) == 0x35000000) ||      /* cbnz */
+           ((inst & 0x7f000000) == 0x34000000)) {      /* cbz */
+               return SignExtend(19, INSN_FMT_IMM19(inst), 4) + pc;
+       }
+
+       if (((inst & 0x7f000000) == 0x37000000) ||      /* tbnz */
+           ((inst & 0x7f000000) == 0x36000000)) {      /* tbz */
+               return SignExtend(14, INSN_FMT_IMM14(inst), 4) + pc;
+       }
+
+       panic("branch_taken: botch");
 }
 
 bool
 db_inst_unconditional_flow_transfer(db_expr_t inst)
 {
-       /* XXX */
+       if (((inst & 0xfffffc1f) == 0xd65f0000) ||      /* ret xN */
+           ((inst & 0xfc000000) == 0x94000000) ||      /* bl */
+           ((inst & 0xfffffc1f) == 0xd63f0000) ||      /* blr */
+           ((inst & 0xfc000000) == 0x14000000) ||      /* b imm */
+           ((inst & 0xfffffc1f) == 0xd61f0000))        /* br */
+               return true;
+
+#define INSN_FMT_COND(insn)    ((insn) & 0xf)
+#define CONDITION_AL   14
+
+       if (((inst & 0xff000010) == 0x54000000) &&      /* b.cond */
+           (INSN_FMT_COND(inst) == CONDITION_AL))      /* always? */
+               return true;
+
        return false;
 }
-



Home | Main Index | Thread Index | Old Index