Module Name:    src
Committed By:   thorpej
Date:           Mon Jun 21 02:01:13 UTC 2021

Modified Files:
        src/sys/arch/alpha/alpha: db_disasm.c db_instruction.h

Log Message:
Allow alpha_print_instruction() to be called from outside DDB, and
allow the caller to supply a buffer to contain the pretty-printed
insn string, rather than db_printf() (which is used if there is no
supplied buffer).


To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.17 src/sys/arch/alpha/alpha/db_disasm.c
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/alpha/alpha/db_instruction.h

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/alpha/alpha/db_disasm.c
diff -u src/sys/arch/alpha/alpha/db_disasm.c:1.16 src/sys/arch/alpha/alpha/db_disasm.c:1.17
--- src/sys/arch/alpha/alpha/db_disasm.c:1.16	Thu Mar 20 20:51:40 2014
+++ src/sys/arch/alpha/alpha/db_disasm.c	Mon Jun 21 02:01:13 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: db_disasm.c,v 1.16 2014/03/20 20:51:40 christos Exp $ */
+/* $NetBSD: db_disasm.c,v 1.17 2021/06/21 02:01:13 thorpej Exp $ */
 
 /*
  * Mach Operating System
@@ -48,7 +48,7 @@
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.16 2014/03/20 20:51:40 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.17 2021/06/21 02:01:13 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -781,31 +781,47 @@ static const char * const name_of_regist
 	"t10",	"t11",	"ra",	"pv",	"at",	"gp",	"sp",	"zero"
 };
 
-static int regcount;		/* how many regs used in this inst */
-static int regnum[3];		/* which regs used in this inst */
-
 static const char *
-register_name(int ireg)
+register_name(struct alpha_print_instruction_context *ctx, int ireg)
 {
 	int	i;
 
-	for (i = 0; i < regcount; i++)
-		if (regnum[i] == ireg)
+	for (i = 0; i < ctx->regcount; i++)
+		if (ctx->regnum[i] == ireg)
 			break;
-	if (i >= regcount)
-		regnum[regcount++] = ireg;
+	if (i >= ctx->regcount)
+		ctx->regnum[ctx->regcount++] = ireg;
 	return (name_of_register[ireg]);
 }
 
+static void
+insn_printf(struct alpha_print_instruction_context *ctx,
+    const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+
+	if (ctx->buf != NULL) {
+		if (ctx->cursor < ctx->bufsize) {
+			ctx->cursor += vsnprintf(ctx->buf + ctx->cursor,
+			    ctx->bufsize - ctx->cursor, fmt, ap);
+		}
+	} else {
+		db_vprintf(fmt, ap);
+	}
+
+	va_end(ap);
+}
+
 /*
  * Disassemble instruction at 'loc'.  'altfmt' specifies an
  * (optional) alternate format.  Return address of start of
  * next instruction.
  */
 
-static int
-alpha_print_instruction(db_addr_t iadr, alpha_instruction i,
-    bool showregs)
+int
+alpha_print_instruction(struct alpha_print_instruction_context *ctx)
 {
 	const char	*opcode;
 	int		ireg;
@@ -813,18 +829,19 @@ alpha_print_instruction(db_addr_t iadr, 
 	bool		fstore;
 	pal_instruction	p;
 
-	regcount = 0;
+	ctx->regcount = 0;
 	fstore = false;
-	opcode = op_name[i.mem_format.opcode];
+	opcode = op_name[ctx->insn.mem_format.opcode];
 
 	/*
 	 *	Dispatch directly on the opcode, save code
 	 *	duplication sometimes via "harmless gotos".
 	 */
-	switch (i.mem_format.opcode) {
+	switch (ctx->insn.mem_format.opcode) {
 	case op_pal:
 		/* "call_pal" is a long string; just use a space. */
-		db_printf("%s %s", opcode, pal_opname(i.pal_format.function));
+		insn_printf(ctx, "%s %s", opcode,
+		    pal_opname(ctx->insn.pal_format.function));
 		break;
 	case op_lda:
 	case op_ldah:
@@ -846,49 +863,54 @@ alpha_print_instruction(db_addr_t iadr, 
 		 * For this and the following three groups we
 		 * just need different opcode strings
 		 */
-		opcode = arit_name(i.operate_lit_format.function);
+		opcode = arit_name(ctx->insn.operate_lit_format.function);
 		goto operate;
 		break;
 	case op_logical:
-		opcode = logical_name(i.operate_lit_format.function);
+		opcode = logical_name(ctx->insn.operate_lit_format.function);
 		goto operate;
 		break;
 	case op_bit:
-		opcode = bitop_name(i.operate_lit_format.function);
+		opcode = bitop_name(ctx->insn.operate_lit_format.function);
 		goto operate;
 		break;
 	case op_mul:
-		opcode = mul_name(i.operate_lit_format.function);
+		opcode = mul_name(ctx->insn.operate_lit_format.function);
 operate:
 		/*
 		 * Nice and uniform, just check for literals
 		 */
-		db_printf("%s\t%s,", opcode,
-		    register_name(i.operate_lit_format.ra));
-		if (i.operate_lit_format.one)
-			db_printf("#0x%x", i.operate_lit_format.literal);
-		else
-			db_printf("%s", register_name(i.operate_reg_format.rb));
-		db_printf(",%s", register_name(i.operate_lit_format.rc));
+		insn_printf(ctx, "%s\t%s,", opcode,
+		    register_name(ctx, ctx->insn.operate_lit_format.ra));
+		if (ctx->insn.operate_lit_format.one) {
+			insn_printf(ctx, "#0x%x",
+			    ctx->insn.operate_lit_format.literal);
+		} else {
+			insn_printf(ctx, "%s",
+			    register_name(ctx,
+					  ctx->insn.operate_reg_format.rb));
+		}
+		insn_printf(ctx, ",%s",
+		    register_name(ctx, ctx->insn.operate_lit_format.rc));
 		break;
 	case op_vax_float:
 		/*
 		 * The three floating point groups are even simpler
 		 */
-		opcode = vaxf_name(i.float_format.function);
+		opcode = vaxf_name(ctx->insn.float_format.function);
 		goto foperate;
 		break;
 	case op_ieee_float:
-		opcode = ieeef_name(i.float_format.function);
+		opcode = ieeef_name(ctx->insn.float_format.function);
 		goto foperate;
 		break;
 	case op_any_float:
-		opcode = anyf_name(i.float_format.function);
+		opcode = anyf_name(ctx->insn.float_format.function);
 foperate:
-		db_printf("%s\tf%d,f%d,f%d", opcode,
-			i.float_format.fa,
-			i.float_format.fb,
-			i.float_format.fc);
+		insn_printf(ctx, "%s\tf%d,f%d,f%d", opcode,
+			ctx->insn.float_format.fa,
+			ctx->insn.float_format.fb,
+			ctx->insn.float_format.fc);
 		break;
 	case op_special:
 		/*
@@ -897,27 +919,30 @@ foperate:
 		{
 			register unsigned int code;
 
-			code = (i.mem_format.displacement)&0xffff;
+			code = (ctx->insn.mem_format.displacement)&0xffff;
 			opcode = special_name(code);
 
 			switch (code) {
 			case op_ecb:
-				db_printf("%s\t(%s)", opcode,
-					register_name(i.mem_format.rb));
+				insn_printf(ctx, "%s\t(%s)", opcode,
+				    register_name(ctx,
+						  ctx->insn.mem_format.rb));
 				break;
 			case op_fetch:
 			case op_fetch_m:
-				db_printf("%s\t0(%s)", opcode,
-					register_name(i.mem_format.rb));
+				insn_printf(ctx, "%s\t0(%s)", opcode,
+				    register_name(ctx,
+						  ctx->insn.mem_format.rb));
 				break;
 			case op_rpcc:
 			case op_rc:
 			case op_rs:
-				db_printf("%s\t%s", opcode,
-					register_name(i.mem_format.ra));
+				insn_printf(ctx, "%s\t%s", opcode,
+				    register_name(ctx,
+						  ctx->insn.mem_format.ra));
 				break;
 			default:
-				db_printf("%s", opcode);
+				insn_printf(ctx, "%s", opcode);
 			break;
 			}
 		}
@@ -927,21 +952,21 @@ foperate:
 		 * Jump instructions really are of two sorts,
 		 * depending on the use of the hint info.
 		 */
-		opcode = jump_name(i.jump_format.action);
-		switch (i.jump_format.action) {
+		opcode = jump_name(ctx->insn.jump_format.action);
+		switch (ctx->insn.jump_format.action) {
 		case op_jmp:
 		case op_jsr:
-			db_printf("%s\t%s,(%s),", opcode,
-				register_name(i.jump_format.ra),
-				register_name(i.jump_format.rb));
-			signed_immediate = i.jump_format.hint;
+			insn_printf(ctx, "%s\t%s,(%s),", opcode,
+			    register_name(ctx, ctx->insn.jump_format.ra),
+			    register_name(ctx, ctx->insn.jump_format.rb));
+			signed_immediate = ctx->insn.jump_format.hint;
 			goto branch_displacement;
 			break;
 		case op_ret:
 		case op_jcr:
-			db_printf("%s\t%s,(%s)", opcode,
-				register_name(i.jump_format.ra),
-				register_name(i.jump_format.rb));
+			insn_printf(ctx, "%s\t%s,(%s)", opcode,
+			    register_name(ctx, ctx->insn.jump_format.ra),
+			    register_name(ctx, ctx->insn.jump_format.rb));
 			break;
 		}
 		break;
@@ -949,30 +974,30 @@ foperate:
 		/*
 		 * These are just in "operate" format.
 		 */
-		opcode = intmisc_name(i.operate_lit_format.function);
+		opcode = intmisc_name(ctx->insn.operate_lit_format.function);
 		goto operate;
 		break;
 			/* HW instructions, possibly chip-specific XXXX */
 	case op_pal19:	/* "hw_mfpr" */
 	case op_pal1d:	/* "hw_mtpr" */
-		p.bits = i.bits;
-		db_printf("\t%s%s\t%s, %d", opcode,
+		p.bits = ctx->insn.bits;
+		insn_printf(ctx, "\t%s%s\t%s, %d", opcode,
 			mXpr_name[p.mXpr_format.regset],
-			register_name(p.mXpr_format.rd),
+			register_name(ctx, p.mXpr_format.rd),
 			p.mXpr_format.index);
 		break;
 	case op_pal1b:	/* "hw_ld" */
 	case op_pal1f:	/* "hw_st" */
-		p.bits = i.bits;
-		db_printf("\t%s%c%s\t%s,", opcode,
+		p.bits = ctx->insn.bits;
+		insn_printf(ctx, "\t%s%c%s\t%s,", opcode,
 			(p.mem_format.qw) ? 'q' : 'l',
 			hwlds_name[p.mem_format.qualif],
-			register_name(p.mem_format.rd));
+			register_name(ctx, p.mem_format.rd));
 		signed_immediate = (long)p.mem_format.displacement;
 		goto loadstore_address;
 
 	case op_pal1e:	/* "hw_rei" */
-		db_printf("\t%s", opcode);
+		insn_printf(ctx, "\t%s", opcode);
 		break;
 
 	case op_ldf:
@@ -997,28 +1022,31 @@ foperate:
 		 * Memory operations, including floats
 		 */
 loadstore:
-		if (fstore)
-		    db_printf("%s\tf%d,", opcode, i.mem_format.ra);
-		else
-		    db_printf("%s\t%s,", opcode,
-		        register_name(i.mem_format.ra));
-		signed_immediate = (long)i.mem_format.displacement;
+		if (fstore) {
+			insn_printf(ctx, "%s\tf%d,", opcode,
+			    ctx->insn.mem_format.ra);
+		} else {
+			insn_printf(ctx, "%s\t%s,", opcode,
+			    register_name(ctx, ctx->insn.mem_format.ra));
+		}
+		signed_immediate = (long)ctx->insn.mem_format.displacement;
 loadstore_address:
 		{
 			char tbuf[24];
 
 			db_format_hex(tbuf, 24, signed_immediate, false);
-			db_printf("%s(%s)", tbuf,
-				register_name(i.mem_format.rb));
+			insn_printf(ctx, "%s(%s)", tbuf,
+			    register_name(ctx, ctx->insn.mem_format.rb));
 		}
 		/*
 		 * For convenience, do the address computation
 		 */
-		if (showregs) {
-			if (i.mem_format.opcode == op_ldah)
+		if (ctx->showregs) {
+			if (ctx->insn.mem_format.opcode == op_ldah)
 				signed_immediate <<= 16;
-			db_printf(" <0x%lx>", signed_immediate +
-			    db_register_value(DDB_REGS, i.mem_format.rb));
+			insn_printf(ctx, " <0x%lx>", signed_immediate +
+			    db_register_value(DDB_REGS,
+					      ctx->insn.mem_format.rb));
 		}
 		break;
 	case op_br:
@@ -1040,45 +1068,54 @@ loadstore_address:
 		/*
 		 * We want to know where we are branching to
 		 */
-		signed_immediate = (long)i.branch_format.displacement;
-		db_printf("%s\t%s,", opcode,
-			  register_name(i.branch_format.ra));
+		signed_immediate = (long)ctx->insn.branch_format.displacement;
+		insn_printf(ctx, "%s\t%s,", opcode,
+		    register_name(ctx, ctx->insn.branch_format.ra));
 branch_displacement:
-		db_printsym(iadr + sizeof(alpha_instruction) +
-		    (signed_immediate << 2), DB_STGY_PROC, db_printf);
+		if (ctx->buf == NULL) {
+			db_printsym(ctx->pc + sizeof(alpha_instruction) +
+			    (signed_immediate << 2), DB_STGY_PROC, db_printf);
+		}
 		break;
 	default:
 		/*
 		 * Shouldn't happen
 		 */
-		db_printf("? 0x%x ?", i.bits);
+		insn_printf(ctx, "? 0x%x ?", ctx->insn.bits);
 	}
 
 	/*
 	 *	Print out the registers used in this instruction
 	 */
-	if (showregs && regcount > 0) {
-		db_printf("\t<");
-		for (ireg = 0; ireg < regcount; ireg++) {
+	if (ctx->showregs && ctx->regcount > 0) {
+		insn_printf(ctx, "\t<");
+		for (ireg = 0; ireg < ctx->regcount; ireg++) {
 			if (ireg != 0)
-				db_printf(",");
-			db_printf("%s=0x%lx",
-			    name_of_register[regnum[ireg]],
-			    db_register_value(DDB_REGS, regnum[ireg]));
+				insn_printf(ctx, ",");
+			insn_printf(ctx, "%s=0x%lx",
+			    name_of_register[ctx->regnum[ireg]],
+			    db_register_value(DDB_REGS, ctx->regnum[ireg]));
 		}
-		db_printf(">");
+		insn_printf(ctx, ">");
 	}
-	db_printf("\n");
+
+	/* If printing into a buffer, skip the newline. */
+	if (ctx->buf == NULL) {
+		insn_printf(ctx, "\n");
+	}
+
 	return (sizeof(alpha_instruction));
 }
 
 db_addr_t
 db_disasm(db_addr_t loc, bool altfmt)
 {
-	alpha_instruction inst;
-
-	inst.bits = db_get_value(loc, 4, 0);
+	struct alpha_print_instruction_context ctx = {
+		.insn.bits = db_get_value(loc, 4, 0),
+		.pc = loc,
+		.showregs = altfmt,
+	};
 
-	loc += alpha_print_instruction(loc, inst, altfmt);
-	return (loc);
+	loc += alpha_print_instruction(&ctx);
+	return loc;
 }

Index: src/sys/arch/alpha/alpha/db_instruction.h
diff -u src/sys/arch/alpha/alpha/db_instruction.h:1.10 src/sys/arch/alpha/alpha/db_instruction.h:1.11
--- src/sys/arch/alpha/alpha/db_instruction.h:1.10	Tue Jul 21 13:37:18 2020
+++ src/sys/arch/alpha/alpha/db_instruction.h	Mon Jun 21 02:01:13 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: db_instruction.h,v 1.10 2020/07/21 13:37:18 thorpej Exp $ */
+/* $NetBSD: db_instruction.h,v 1.11 2021/06/21 02:01:13 thorpej Exp $ */
 
 /*
  * Copyright (c) 1999 Christopher G. Demetriou.  All rights reserved.
@@ -741,5 +741,19 @@ typedef union {
 #define	op_cvtgd_su	0x5ad
 #define	op_cvtgqg_sv	0x5af
 
+#ifdef _KERNEL
+struct alpha_print_instruction_context {
+	unsigned long pc;	/* address of insn */
+	alpha_instruction insn;	/* instruction bits */
+	char	*buf;		/* output buffer (if not DDB) */
+	size_t	bufsize;	/* size of output buffer */
+	size_t	cursor;		/* current next output location */
+	int	regcount;	/* how many rebgs used in this insn */
+	int	regnum[3];	/* which regs are used in this insn */
+	bool	showregs;	/* show registers */
+};
+
+int	alpha_print_instruction(struct alpha_print_instruction_context *);
+#endif /* _KERNEL */
 
 #endif	/* _ALPHA_INSTRUCTION_H_ */

Reply via email to