Module Name: src
Committed By: ryo
Date: Thu May 31 09:37:16 UTC 2018
Modified Files:
src/sys/arch/aarch64/aarch64: db_interface.c
Log Message:
implement properly branch_taken() and inst_unconditional_flow_transfer().
To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/aarch64/aarch64/db_interface.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/aarch64/aarch64/db_interface.c
diff -u src/sys/arch/aarch64/aarch64/db_interface.c:1.2 src/sys/arch/aarch64/aarch64/db_interface.c:1.3
--- src/sys/arch/aarch64/aarch64/db_interface.c:1.2 Sun Apr 1 04:35:03 2018
+++ src/sys/arch/aarch64/aarch64/db_interface.c Thu May 31 09:37:16 2018
@@ -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 <[email protected]>
@@ -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 @@ db_write_bytes(vaddr_t addr, size_t size
}
}
+/*
+ * 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;
}
-