199730Sbenno/*	$FreeBSD$	*/
299730Sbenno/*	$NetBSD: db_disasm.c,v 1.12 2002/01/05 22:07:26 jhawk Exp $	*/
399730Sbenno/*	$OpenBSD: db_disasm.c,v 1.2 1996/12/28 06:21:48 rahnds Exp $	*/
499730Sbenno
599730Sbenno#include <sys/param.h>
699730Sbenno#include <sys/proc.h>
799730Sbenno#include <sys/systm.h>
899730Sbenno
999730Sbenno#include <machine/db_machdep.h>
1099730Sbenno#include <machine/trap.h>
1199730Sbenno
1299730Sbenno#include <ddb/ddb.h>
1399730Sbenno#include <ddb/db_access.h>
1499730Sbenno#include <ddb/db_sym.h>
1599730Sbenno#include <ddb/db_variables.h>
1699730Sbenno#include <ddb/db_output.h>
1799730Sbenno
1899730Sbennoenum function_mask {
1999730Sbenno	Op_A    =	0x00000001,
2099730Sbenno	Op_B    =	0x00000002,
2199730Sbenno	Op_BI   =	0x00000004,
2299730Sbenno	Op_BO   =	0x00000008,
2399730Sbenno	Op_CRM  =	0x00000010,
2499730Sbenno	Op_D    =	0x00000020, /* yes, Op_S and Op_D are the same */
2599730Sbenno	Op_S    =	0x00000020,
2699730Sbenno	Op_FM   =	0x00000040,
2799730Sbenno	Op_IMM  =	0x00000080,
2899730Sbenno	Op_LK   =	0x00000100,
2999730Sbenno	Op_Rc   =	0x00000200,
3099730Sbenno	Op_AA	=	Op_LK | Op_Rc, /* kludge (reduce Op_s) */
3199730Sbenno	Op_LKM	=	Op_AA,
3299730Sbenno	Op_RcM	=	Op_AA,
3399730Sbenno	Op_OE   =	0x00000400,
3499730Sbenno	Op_SR   =	0x00000800,
3599730Sbenno	Op_TO   =	0x00001000,
3699730Sbenno	Op_sign =	0x00002000,
3799730Sbenno	Op_const =	0x00004000,
3899730Sbenno	Op_SIMM =	Op_const | Op_sign,
3999730Sbenno	Op_UIMM =	Op_const,
4099730Sbenno	Op_d	=	Op_const | Op_sign,
4199730Sbenno	Op_crbA =	0x00008000,
4299730Sbenno	Op_crbB =	0x00010000,
4399730Sbenno	Op_WS	=	Op_crbB,	/* kludge, same field as crbB */
4499730Sbenno	Op_crbD =	0x00020000,
4599730Sbenno	Op_crfD =	0x00040000,
4699730Sbenno	Op_crfS =	0x00080000,
4799730Sbenno	Op_ds   =	0x00100000,
4899730Sbenno	Op_me   =	0x00200000,
4999730Sbenno	Op_spr  =	0x00400000,
5099730Sbenno	Op_dcr  =	Op_spr,		/* out of bits - cheat with Op_spr */
5199730Sbenno	Op_tbr  =	0x00800000,
5299730Sbenno
5399730Sbenno	Op_L	=	0x01000000,
5499730Sbenno	Op_BD	=	0x02000000,
5599730Sbenno	Op_LI	=	0x04000000,
5699730Sbenno	Op_C	=	0x08000000,
5799730Sbenno
5899730Sbenno	Op_NB	=	0x10000000,
5999730Sbenno
6099730Sbenno	Op_sh_mb_sh =	0x20000000,
6199730Sbenno	Op_sh   =	0x40000000,
6299730Sbenno	Op_SH	=	Op_sh | Op_sh_mb_sh,
6399730Sbenno	Op_mb	=	0x80000000,
6499730Sbenno	Op_MB	=	Op_mb | Op_sh_mb_sh,
6599730Sbenno	Op_ME	=	Op_MB,
6699730Sbenno
6799730Sbenno};
6899730Sbenno
6999730Sbennostruct opcode {
7099730Sbenno	char *name;
7199730Sbenno	u_int32_t mask;
7299730Sbenno	u_int32_t code;
7399730Sbenno	enum function_mask func;
7499730Sbenno};
7599730Sbenno
7699730Sbennotypedef u_int32_t instr_t;
7799730Sbennotypedef void (op_class_func) (instr_t, vm_offset_t);
7899730Sbenno
7999730Sbennou_int32_t extract_field(u_int32_t value, u_int32_t base, u_int32_t width);
8099730Sbennovoid disasm_fields(const struct opcode *popcode, instr_t instr, vm_offset_t loc,
8199730Sbenno    char *disasm_str);
8299730Sbennovoid dis_ppc(const struct opcode *opcodeset, instr_t instr, vm_offset_t loc);
8399730Sbenno
8499730Sbennoop_class_func op_ill, op_base;
8599730Sbennoop_class_func op_cl_x13, op_cl_x1e, op_cl_x1f;
8699730Sbennoop_class_func op_cl_x3a, op_cl_x3b;
8799730Sbennoop_class_func op_cl_x3e, op_cl_x3f;
8899730Sbenno
8999730Sbennoop_class_func *opcodes_base[] = {
9099730Sbenno/*x00*/	op_ill,		op_ill,		op_base,	op_ill,
9199730Sbenno/*x04*/	op_ill,		op_ill,		op_ill,		op_base,
9299730Sbenno/*x08*/	op_base,	op_base,	op_ill,		op_base,
9399730Sbenno/*x0C*/ op_base,	op_base,	op_base/*XXX*/,	op_base/*XXX*/,
9499730Sbenno/*x10*/ op_base,	op_base,	op_base,	op_cl_x13,
9599730Sbenno/*x14*/	op_base,	op_base,	op_ill,		op_base,
9699730Sbenno/*x18*/	op_base,	op_base,	op_base,	op_base,
9799730Sbenno/*x1C*/ op_base,	op_base,	op_cl_x1e,	op_cl_x1f,
9899730Sbenno/*x20*/	op_base,	op_base,	op_base,	op_base,
9999730Sbenno/*x24*/	op_base,	op_base,	op_base,	op_base,
10099730Sbenno/*x28*/	op_base,	op_base,	op_base,	op_base,
10199730Sbenno/*x2C*/	op_base,	op_base,	op_base,	op_base,
10299730Sbenno/*x30*/	op_base,	op_base,	op_base,	op_base,
10399730Sbenno/*x34*/	op_base,	op_base,	op_base,	op_base,
10499730Sbenno/*x38*/ op_ill,		op_ill,		op_cl_x3a,	op_cl_x3b,
10599730Sbenno/*x3C*/	op_ill,		op_ill,		op_cl_x3e,	op_cl_x3f
10699730Sbenno};
10799730Sbenno
10899730Sbenno
10999730Sbenno/* This table could be modified to make significant the "reserved" fields
11099730Sbenno * of the opcodes, But I didn't feel like it when typing in the table,
11199730Sbenno * I would recommend that this table be looked over for errors,
11299730Sbenno * This was derived from the table in Appendix A.2 of (Mot part # MPCFPE/AD)
11399730Sbenno * PowerPC Microprocessor Family: The Programming Environments
11499730Sbenno */
11599730Sbenno
11699730Sbennoconst struct opcode opcodes[] = {
11799730Sbenno	{ "tdi",	0xfc000000, 0x08000000, Op_TO | Op_A | Op_SIMM },
11899730Sbenno	{ "twi",	0xfc000000, 0x0c000000, Op_TO | Op_A | Op_SIMM },
11999730Sbenno	{ "mulli",	0xfc000000, 0x1c000000, Op_D | Op_A | Op_SIMM },
12099730Sbenno	{ "subfic",	0xfc000000, 0x20000000, Op_D | Op_A | Op_SIMM },
12199730Sbenno	{ "cmpli",	0xfc000000, 0x28000000, Op_crfD | Op_L | Op_A | Op_SIMM },
12299730Sbenno	{ "cmpi",	0xfc000000, 0x2c000000, Op_crfD | Op_L | Op_A | Op_SIMM },
12399730Sbenno	{ "addic",	0xfc000000, 0x30000000, Op_D | Op_A | Op_SIMM },
12499730Sbenno	{ "addic.",	0xfc000000, 0x34000000, Op_D | Op_A | Op_SIMM },
12599730Sbenno	{ "addi",	0xfc000000, 0x38000000, Op_D | Op_A | Op_SIMM },
12699730Sbenno	{ "addis",	0xfc000000, 0x3c000000, Op_D | Op_A | Op_SIMM },
12799730Sbenno	{ "bc",		0xfc000000, 0x40000000, Op_BO | Op_BI | Op_BD | Op_AA | Op_LK },
12899730Sbenno	{ "sc",		0xffffffff, 0x44000002, Op_BO | Op_BI | Op_BD | Op_AA | Op_LK },
12999730Sbenno	{ "b",		0xfc000000, 0x48000000, Op_LI | Op_AA | Op_LK },
13099730Sbenno
13199730Sbenno	{ "rlwimi",	0xfc000000, 0x50000000, Op_S | Op_A | Op_SH | Op_MB | Op_ME | Op_Rc },
13299730Sbenno	{ "rlwinm",	0xfc000000, 0x54000000, Op_S | Op_A | Op_SH | Op_MB | Op_ME | Op_Rc },
13399730Sbenno	{ "rlwnm",	0xfc000000, 0x5c000000, Op_S | Op_A | Op_SH | Op_MB | Op_ME | Op_Rc },
13499730Sbenno
13599730Sbenno	{ "ori",	0xfc000000, 0x60000000, Op_S | Op_A | Op_UIMM },
13699730Sbenno	{ "oris",	0xfc000000, 0x64000000, Op_S | Op_A | Op_UIMM },
13799730Sbenno	{ "xori",	0xfc000000, 0x68000000, Op_S | Op_A | Op_UIMM },
13899730Sbenno	{ "xoris",	0xfc000000, 0x6c000000, Op_S | Op_A | Op_UIMM },
13999730Sbenno
14099730Sbenno	{ "andi.",	0xfc000000, 0x70000000, Op_S | Op_A | Op_UIMM },
14199730Sbenno	{ "andis.",	0xfc000000, 0x74000000, Op_S | Op_A | Op_UIMM },
14299730Sbenno
14399730Sbenno	{ "lwz",	0xfc000000, 0x80000000, Op_D | Op_A | Op_d },
14499730Sbenno	{ "lwzu",	0xfc000000, 0x84000000, Op_D | Op_A | Op_d },
14599730Sbenno	{ "lbz",	0xfc000000, 0x88000000, Op_D | Op_A | Op_d },
14699730Sbenno	{ "lbzu",	0xfc000000, 0x8c000000, Op_D | Op_A | Op_d },
14799730Sbenno	{ "stw",	0xfc000000, 0x90000000, Op_S | Op_A | Op_d },
14899730Sbenno	{ "stwu",	0xfc000000, 0x94000000, Op_S | Op_A | Op_d },
14999730Sbenno	{ "stb",	0xfc000000, 0x98000000, Op_S | Op_A | Op_d },
15099730Sbenno	{ "stbu",	0xfc000000, 0x9c000000, Op_S | Op_A | Op_d },
15199730Sbenno
15299730Sbenno	{ "lhz",	0xfc000000, 0xa0000000, Op_D | Op_A | Op_d },
15399730Sbenno	{ "lhzu",	0xfc000000, 0xa4000000, Op_D | Op_A | Op_d },
15499730Sbenno	{ "lha",	0xfc000000, 0xa8000000, Op_D | Op_A | Op_d },
15599730Sbenno	{ "lhau",	0xfc000000, 0xac000000, Op_D | Op_A | Op_d },
15699730Sbenno	{ "sth",	0xfc000000, 0xb0000000, Op_S | Op_A | Op_d },
15799730Sbenno	{ "sthu",	0xfc000000, 0xb4000000, Op_S | Op_A | Op_d },
15899730Sbenno	{ "lmw",	0xfc000000, 0xb8000000, Op_D | Op_A | Op_d },
15999730Sbenno	{ "stmw",	0xfc000000, 0xbc000000, Op_S | Op_A | Op_d },
16099730Sbenno
16199730Sbenno	{ "lfs",	0xfc000000, 0xc0000000, Op_D | Op_A | Op_d },
16299730Sbenno	{ "lfsu",	0xfc000000, 0xc4000000, Op_D | Op_A | Op_d },
16399730Sbenno	{ "lfd",	0xfc000000, 0xc8000000, Op_D | Op_A | Op_d },
16499730Sbenno	{ "lfdu",	0xfc000000, 0xcc000000, Op_D | Op_A | Op_d },
16599730Sbenno
16699730Sbenno	{ "stfs",	0xfc000000, 0xd0000000, Op_S | Op_A | Op_d },
16799730Sbenno	{ "stfsu",	0xfc000000, 0xd4000000, Op_S | Op_A | Op_d },
16899730Sbenno	{ "stfd",	0xfc000000, 0xd8000000, Op_S | Op_A | Op_d },
16999730Sbenno	{ "stfdu",	0xfc000000, 0xdc000000, Op_S | Op_A | Op_d },
17099730Sbenno	{ "",		0x0,		0x0, 0 }
17199730Sbenno
17299730Sbenno};
17399730Sbenno/* 13 * 4 = 4c */
17499730Sbennoconst struct opcode opcodes_13[] = {
17599730Sbenno/* 0x13 << 2 */
17699730Sbenno	{ "mcrf",	0xfc0007fe, 0x4c000000, Op_crfD | Op_crfS },
17799730Sbenno	{ "bclr",	0xfc0007fe, 0x4c000020, Op_BO | Op_BI | Op_LK },
17899730Sbenno	{ "crnor",	0xfc0007fe, 0x4c000042, Op_crbD | Op_crbA | Op_crbB },
17999730Sbenno	{ "rfi",	0xfc0007fe, 0x4c000064, 0 },
18099730Sbenno	{ "crandc",	0xfc0007fe, 0x4c000102, Op_BO | Op_BI | Op_LK },
18199730Sbenno	{ "isync",	0xfc0007fe, 0x4c00012c, 0 },
18299730Sbenno	{ "crxor",	0xfc0007fe, 0x4c000182, Op_crbD | Op_crbA | Op_crbB },
18399730Sbenno	{ "crnand",	0xfc0007fe, 0x4c0001c2, Op_crbD | Op_crbA | Op_crbB },
18499730Sbenno	{ "crand",	0xfc0007fe, 0x4c000202, Op_crbD | Op_crbA | Op_crbB },
18599730Sbenno	{ "creqv",	0xfc0007fe, 0x4c000242, Op_crbD | Op_crbA | Op_crbB },
18699730Sbenno	{ "crorc",	0xfc0007fe, 0x4c000342, Op_crbD | Op_crbA | Op_crbB },
18799730Sbenno	{ "cror",	0xfc0007fe, 0x4c000382, Op_crbD | Op_crbA | Op_crbB },
18899730Sbenno	{ "bcctr",	0xfc0007fe, 0x4c000420, Op_BO | Op_BI | Op_LK },
18999730Sbenno	{ "",		0x0,		0x0, 0 }
19099730Sbenno};
19199730Sbenno
19299730Sbenno/* 1e * 4 = 78 */
19399730Sbennoconst struct opcode opcodes_1e[] = {
19499730Sbenno	{ "rldicl",	0xfc00001c, 0x78000000, Op_S | Op_A | Op_sh | Op_mb | Op_Rc },
19599730Sbenno	{ "rldicr",	0xfc00001c, 0x78000004, Op_S | Op_A | Op_sh | Op_me | Op_Rc },
19699730Sbenno	{ "rldic",	0xfc00001c, 0x78000008, Op_S | Op_A | Op_sh | Op_mb | Op_Rc },
19799730Sbenno	{ "rldimi",	0xfc00001c, 0x7800000c, Op_S | Op_A | Op_sh | Op_mb | Op_Rc },
19899730Sbenno	{ "rldcl",	0xfc00003e, 0x78000010, Op_S | Op_A | Op_B | Op_mb | Op_Rc },
19999730Sbenno	{ "rldcr",	0xfc00003e, 0x78000012, Op_S | Op_A | Op_B | Op_me | Op_Rc },
20099730Sbenno	{ "",		0x0,		0x0, 0 }
20199730Sbenno};
20299730Sbenno
20399730Sbenno/* 1f * 4 = 7c */
20499730Sbennoconst struct opcode opcodes_1f[] = {
20599730Sbenno/* 1f << 2 */
20699730Sbenno	{ "cmp",	0xfc0007fe, 0x7c000000, Op_S | Op_A | Op_B | Op_me | Op_Rc },
20799730Sbenno	{ "tw",		0xfc0007fe, 0x7c000008, Op_TO | Op_A | Op_B },
20899730Sbenno	{ "subfc",	0xfc0003fe, 0x7c000010, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
20999730Sbenno	{ "mulhdu",	0xfc0007fe, 0x7c000012, Op_D | Op_A | Op_B | Op_Rc },
21099730Sbenno	{ "addc",	0xfc0003fe, 0x7c000014, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
21199730Sbenno	{ "mulhwu",	0xfc0007fe, 0x7c000016, Op_D | Op_A | Op_B | Op_Rc },
21299730Sbenno
21399730Sbenno	{ "mfcr",	0xfc0007fe, 0x7c000026, Op_D },
21499730Sbenno	{ "lwarx",	0xfc0007fe, 0x7c000028, Op_D | Op_A | Op_B },
21599730Sbenno	{ "ldx",	0xfc0007fe, 0x7c00002a, Op_D | Op_A | Op_B },
21699730Sbenno	{ "lwzx",	0xfc0007fe, 0x7c00002e, Op_D | Op_A | Op_B },
21799730Sbenno	{ "slw",	0xfc0007fe, 0x7c000030, Op_D | Op_A | Op_B | Op_Rc },
21899730Sbenno	{ "cntlzw",	0xfc0007fe, 0x7c000034, Op_D | Op_A | Op_Rc },
21999730Sbenno	{ "sld",	0xfc0007fe, 0x7c000036, Op_D | Op_A | Op_B | Op_Rc },
22099730Sbenno	{ "and",	0xfc0007fe, 0x7c000038, Op_D | Op_A | Op_B | Op_Rc },
22199730Sbenno	{ "cmpl",	0xfc0007fe, 0x7c000040, Op_crfD | Op_L | Op_A | Op_B },
22299730Sbenno	{ "subf",	0xfc0003fe, 0x7c000050, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
22399730Sbenno	{ "ldux",	0xfc0007fe, 0x7c00006a, Op_D | Op_A | Op_B },
22499730Sbenno	{ "dcbst",	0xfc0007fe, 0x7c00006c, Op_A | Op_B },
22599730Sbenno	{ "lwzux",	0xfc0007fe, 0x7c00006e, Op_D | Op_A | Op_B },
22699730Sbenno	{ "cntlzd",	0xfc0007fe, 0x7c000074, Op_S | Op_A | Op_Rc },
22799730Sbenno	{ "andc",	0xfc0007fe, 0x7c000078, Op_S | Op_A | Op_B | Op_Rc },
22899730Sbenno	{ "td",		0xfc0007fe, 0x7c000088, Op_TO | Op_A | Op_B },
22999730Sbenno	{ "mulhd",	0xfc0007fe, 0x7c000092, Op_D | Op_A | Op_B | Op_Rc },
23099730Sbenno	{ "mulhw",	0xfc0007fe, 0x7c000096, Op_D | Op_A | Op_B | Op_Rc },
23199730Sbenno	{ "mfmsr",	0xfc0007fe, 0x7c0000a6, Op_D },
23299730Sbenno	{ "ldarx",	0xfc0007fe, 0x7c0000a8, Op_D | Op_A | Op_B },
23399730Sbenno	{ "dcbf",	0xfc0007fe, 0x7c0000ac, Op_A | Op_B },
23499730Sbenno	{ "lbzx",	0xfc0007fe, 0x7c0000ae, Op_D | Op_A | Op_B },
23599730Sbenno	{ "neg",	0xfc0003fe, 0x7c0000d0, Op_D | Op_A | Op_OE | Op_Rc },
23699730Sbenno	{ "lbzux",	0xfc0007fe, 0x7c0000ee, Op_D | Op_A | Op_B },
23799730Sbenno	{ "nor",	0xfc0007fe, 0x7c0000f8, Op_S | Op_A | Op_B | Op_Rc },
23899730Sbenno	{ "wrtee",	0xfc0003ff, 0x7c000106, Op_S },
23999730Sbenno	{ "subfe",	0xfc0003fe, 0x7c000110, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
24099730Sbenno	{ "adde",	0xfc0003fe, 0x7c000114, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
24199730Sbenno	{ "mtcrf",	0xfc0007fe, 0x7c000120, Op_S | Op_CRM },
24299730Sbenno	{ "mtmsr",	0xfc0007fe, 0x7c000124, Op_S },
24399730Sbenno	{ "stdx",	0xfc0007fe, 0x7c00012a, Op_S | Op_A | Op_B },
24499730Sbenno	{ "stwcx.",	0xfc0007ff, 0x7c00012d, Op_S | Op_A | Op_B },
24599730Sbenno	{ "stwx",	0xfc0007fe, 0x7c00012e, Op_S | Op_A | Op_B },
24699730Sbenno	{ "wrteei",	0xfc0003fe, 0x7c000146 },	/* XXX: out of flags! */
24799730Sbenno	{ "stdux",	0xfc0007fe, 0x7c00016a, Op_S | Op_A | Op_B },
24899730Sbenno	{ "stwux",	0xfc0007fe, 0x7c00016e, Op_S | Op_A | Op_B },
24999730Sbenno	{ "subfze",	0xfc0003fe, 0x7c000190, Op_D | Op_A | Op_OE | Op_Rc },
25099730Sbenno	{ "addze",	0xfc0003fe, 0x7c000194, Op_D | Op_A | Op_OE | Op_Rc },
25199730Sbenno	{ "mtsr",	0xfc0007fe, 0x7c0001a4, Op_S | Op_SR },
25299730Sbenno	{ "stdcx.",	0xfc0007ff, 0x7c0001ad, Op_S | Op_A | Op_B },
25399730Sbenno	{ "stbx",	0xfc0007fe, 0x7c0001ae, Op_S | Op_A | Op_B },
25499730Sbenno	{ "subfme",	0xfc0003fe, 0x7c0001d0, Op_D | Op_A | Op_OE | Op_Rc },
25599730Sbenno	{ "mulld",	0xfc0003fe, 0x7c0001d2, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
25699730Sbenno	{ "addme",	0xfc0003fe, 0x7c0001d4, Op_D | Op_A | Op_OE | Op_Rc },
25799730Sbenno	{ "mullw",	0xfc0003fe, 0x7c0001d6, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
25899730Sbenno	{ "mtsrin",	0xfc0007fe, 0x7c0001e4, Op_S | Op_B },
25999730Sbenno	{ "dcbtst",	0xfc0007fe, 0x7c0001ec, Op_A | Op_B },
26099730Sbenno	{ "stbux",	0xfc0007fe, 0x7c0001ee, Op_S | Op_A | Op_B },
26199730Sbenno	{ "add",	0xfc0003fe, 0x7c000214, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
26299730Sbenno	{ "dcbt",	0xfc0007fe, 0x7c00022c, Op_A | Op_B },
26399730Sbenno	{ "lhzx",	0xfc0007ff, 0x7c00022e, Op_D | Op_A | Op_B },
26499730Sbenno	{ "eqv",	0xfc0007fe, 0x7c000238, Op_S | Op_A | Op_B | Op_Rc },
26599730Sbenno	{ "tlbie",	0xfc0007fe, 0x7c000264, Op_B },
26699730Sbenno	{ "eciwx",	0xfc0007fe, 0x7c00026c, Op_D | Op_A | Op_B },
26799730Sbenno	{ "lhzux",	0xfc0007fe, 0x7c00026e, Op_D | Op_A | Op_B },
26899730Sbenno	{ "xor",	0xfc0007fe, 0x7c000278, Op_S | Op_A | Op_B | Op_Rc },
26999730Sbenno	{ "mfdcr",	0xfc0007fe, 0x7c000286, Op_D | Op_dcr },
27099730Sbenno	{ "mfspr",	0xfc0007fe, 0x7c0002a6, Op_D | Op_spr },
27199730Sbenno	{ "lwax",	0xfc0007fe, 0x7c0002aa, Op_D | Op_A | Op_B },
27299730Sbenno	{ "lhax",	0xfc0007fe, 0x7c0002ae, Op_D | Op_A | Op_B },
27399730Sbenno	{ "tlbia",	0xfc0007fe, 0x7c0002e4, 0 },
27499730Sbenno	{ "mftb",	0xfc0007fe, 0x7c0002e6, Op_D | Op_tbr },
27599730Sbenno	{ "lwaux",	0xfc0007fe, 0x7c0002ea, Op_D | Op_A | Op_B },
27699730Sbenno	{ "lhaux",	0xfc0007fe, 0x7c0002ee, Op_D | Op_A | Op_B },
27799730Sbenno	{ "sthx",	0xfc0007fe, 0x7c00032e, Op_S | Op_A | Op_B },
27899730Sbenno	{ "orc",	0xfc0007fe, 0x7c000338, Op_S | Op_A | Op_B | Op_Rc },
27999730Sbenno	{ "ecowx",	0xfc0007fe, 0x7c00036c, Op_S | Op_A | Op_B | Op_Rc },
28099730Sbenno	{ "slbie",	0xfc0007fc, 0x7c000364, Op_B },
28199730Sbenno	{ "sthux",	0xfc0007fe, 0x7c00036e, Op_S | Op_A | Op_B },
28299730Sbenno	{ "or",		0xfc0007fe, 0x7c000378, Op_S | Op_A | Op_B | Op_Rc },
28399730Sbenno	{ "mtdcr",	0xfc0007fe, 0x7c000386, Op_S | Op_dcr },
28499730Sbenno	{ "divdu",	0xfc0003fe, 0x7c000392, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
28599730Sbenno	{ "divwu",	0xfc0003fe, 0x7c000396, Op_D | Op_A | Op_B | Op_OE | Op_Rc },
28699730Sbenno	{ "mtspr",	0xfc0007fe, 0x7c0003a6, Op_S | Op_spr },
28799730Sbenno	{ "dcbi",	0xfc0007fe, 0x7c0003ac, Op_A | Op_B },
28899730Sbenno	{ "nand",	0xfc0007fe, 0x7c0003b8, Op_S | Op_A | Op_B | Op_Rc },
28999730Sbenno	{ "dcread",	0xfc0007fe, 0x7c0003cc, Op_D | Op_A | Op_B },
29099730Sbenno	{ "divd",	0xfc0003fe, 0x7c0003d2, Op_S | Op_A | Op_B | Op_OE | Op_Rc },
29199730Sbenno	{ "divw",	0xfc0003fe, 0x7c0003d6, Op_S | Op_A | Op_B | Op_OE | Op_Rc },
29299730Sbenno	{ "slbia",	0xfc0003fe, 0x7c0003e4, Op_S | Op_A | Op_B | Op_OE | Op_Rc },
29399730Sbenno	{ "mcrxr",	0xfc0007fe, 0x7c000400, Op_crfD },
29499730Sbenno	{ "lswx",	0xfc0007fe, 0x7c00042a, Op_D | Op_A | Op_B },
29599730Sbenno	{ "lwbrx",	0xfc0007fe, 0x7c00042c, Op_D | Op_A | Op_B },
29699730Sbenno	{ "lfsx",	0xfc0007fe, 0x7c00042e, Op_D | Op_A | Op_B },
29799730Sbenno	{ "srw",	0xfc0007fe, 0x7c000430, Op_S | Op_A | Op_B | Op_Rc },
29899730Sbenno	{ "srd",	0xfc0007fe, 0x7c000436, Op_S | Op_A | Op_B | Op_Rc },
29999730Sbenno	{ "tlbsync",	0xfc0007fe, 0x7c00046c, 0 },
30099730Sbenno	{ "lfsux",	0xfc0007fe, 0x7c00046e, Op_D | Op_A | Op_B },
30199730Sbenno	{ "mfsr",	0xfc0007fe, 0x7c0004a6, Op_D | Op_SR },
30299730Sbenno	{ "lswi",	0xfc0007fe, 0x7c0004aa, Op_D | Op_A | Op_NB },
30399730Sbenno	{ "sync",	0xfc0007fe, 0x7c0004ac, 0 },
30499730Sbenno	{ "lfdx",	0xfc0007fe, 0x7c0004ae, Op_D | Op_A | Op_B },
30599730Sbenno	{ "lfdux",	0xfc0007fe, 0x7c0004ee, Op_D | Op_A | Op_B },
30699730Sbenno	{ "mfsrin",	0xfc0007fe, 0x7c000526, Op_D | Op_B },
30799730Sbenno	{ "stswx",	0xfc0007fe, 0x7c00052a, Op_S | Op_A | Op_B },
30899730Sbenno	{ "stwbrx",	0xfc0007fe, 0x7c00052c, Op_S | Op_A | Op_B },
30999730Sbenno	{ "stfsx",	0xfc0007fe, 0x7c00052e, Op_S | Op_A | Op_B },
31099730Sbenno	{ "stfsux",	0xfc0007fe, 0x7c00056e, Op_S | Op_A | Op_B },
31199730Sbenno	{ "stswi",	0xfc0007fe, 0x7c0005aa, Op_S | Op_A | Op_NB },
31299730Sbenno	{ "stfdx",	0xfc0007fe, 0x7c0005ae, Op_S | Op_A | Op_B },
31399730Sbenno	{ "stfdux",	0xfc0007fe, 0x7c0005ee, Op_S | Op_A | Op_B },
31499730Sbenno	{ "lhbrx",	0xfc0007fe, 0x7c00062c, Op_D | Op_A | Op_B },
31599730Sbenno	{ "sraw",	0xfc0007fe, 0x7c000630, Op_S | Op_A | Op_B },
31699730Sbenno	{ "srad",	0xfc0007fe, 0x7c000634, Op_S | Op_A | Op_B | Op_Rc },
31799730Sbenno	{ "srawi",	0xfc0007fe, 0x7c000670, Op_S | Op_A | Op_B | Op_Rc },
31899730Sbenno	{ "sradi",	0xfc0007fc, 0x7c000674, Op_S | Op_A | Op_sh },
31999730Sbenno	{ "eieio",	0xfc0007fe, 0x7c0006ac, 0 },
32099730Sbenno	{ "tlbsx",	0xfc0007fe, 0x7c000724, Op_S | Op_A | Op_B | Op_Rc },
32199730Sbenno	{ "sthbrx",	0xfc0007fe, 0x7c00072c, Op_S | Op_A | Op_B },
32299730Sbenno	{ "extsh",	0xfc0007fe, 0x7c000734, Op_S | Op_A | Op_B | Op_Rc },
32399730Sbenno	{ "tlbre",	0xfc0007fe, 0x7c000764, Op_D | Op_A | Op_WS },
32499730Sbenno	{ "extsb",	0xfc0007fe, 0x7c000774, Op_S | Op_A | Op_Rc },
32599730Sbenno	{ "icbi",	0xfc0007fe, 0x7c0007ac, Op_A | Op_B },
32699730Sbenno	{ "tlbwe",	0xfc0007fe, 0x7c0007a4, Op_S | Op_A | Op_WS },
32799730Sbenno	{ "stfiwx",	0xfc0007fe, 0x7c0007ae, Op_S | Op_A | Op_B },
32899730Sbenno	{ "extsw",	0xfc0007fe, 0x7c0007b4, Op_S | Op_A | Op_Rc },
32999730Sbenno	{ "dcbz",	0xfc0007fe, 0x7c0007ec, Op_A | Op_B },
33099730Sbenno	{ "",		0x0,		0x0, 0 }
33199730Sbenno};
33299730Sbenno
33399730Sbenno/* 3a * 4 = e8 */
33499730Sbennoconst struct opcode opcodes_3a[] = {
33599730Sbenno	{ "ld",		0xfc000003, 0xe8000000, Op_D | Op_A | Op_ds },
33699730Sbenno	{ "ldu",	0xfc000003, 0xe8000001, Op_D | Op_A | Op_ds },
33799730Sbenno	{ "lwa",	0xfc000003, 0xe8000002, Op_D | Op_A | Op_ds },
33899730Sbenno	{ "",		0x0,		0x0, 0 }
33999730Sbenno};
34099730Sbenno/* 3b * 4 = ec */
34199730Sbennoconst struct opcode opcodes_3b[] = {
34299730Sbenno	{ "fdivs",	0xfc00003e, 0xec000024, Op_D | Op_A | Op_B | Op_Rc },
34399730Sbenno	{ "fsubs",	0xfc00003e, 0xec000028, Op_D | Op_A | Op_B | Op_Rc },
34499730Sbenno
34599730Sbenno	{ "fadds",	0xfc00003e, 0xec00002a, Op_D | Op_A | Op_B | Op_Rc },
34699730Sbenno	{ "fsqrts",	0xfc00003e, 0xec00002c, Op_D | Op_B | Op_Rc },
34799730Sbenno	{ "fres",	0xfc00003e, 0xec000030, Op_D | Op_B | Op_Rc },
34899730Sbenno	{ "fmuls",	0xfc00003e, 0xec000032, Op_D | Op_A | Op_C | Op_Rc },
34999730Sbenno	{ "fmsubs",	0xfc00003e, 0xec000038, Op_D | Op_A | Op_B | Op_C | Op_Rc },
35099730Sbenno	{ "fmadds",	0xfc00003e, 0xec00003a, Op_D | Op_A | Op_B | Op_C | Op_Rc },
35199730Sbenno	{ "fnmsubs",	0xfc00003e, 0xec00003c, Op_D | Op_A | Op_B | Op_C | Op_Rc },
35299730Sbenno	{ "fnmadds",	0xfc00003e, 0xec00003e, Op_D | Op_A | Op_B | Op_C | Op_Rc },
35399730Sbenno	{ "",		0x0,		0x0, 0 }
35499730Sbenno};
35599730Sbenno/* 3e * 4 = f8 */
35699730Sbennoconst struct opcode opcodes_3e[] = {
35799730Sbenno	{ "std",	0xfc000003, 0xf8000000, Op_S | Op_A | Op_ds },
35899730Sbenno	{ "stdu",	0xfc000003, 0xf8000001, Op_S | Op_A | Op_ds },
35999730Sbenno	{ "",		0x0,		0x0, 0 }
36099730Sbenno};
36199730Sbenno
36299730Sbenno/* 3f * 4 = fc */
36399730Sbennoconst struct opcode opcodes_3f[] = {
36499730Sbenno	{ "fcmpu",	0xfc0007fe, 0xfc000000, Op_crfD | Op_A | Op_B },
36599730Sbenno	{ "frsp",	0xfc0007fe, 0xfc000018, Op_D | Op_B | Op_Rc },
36699730Sbenno	{ "fctiw",	0xfc0007fe, 0xfc00001c, Op_D | Op_B | Op_Rc },
36799730Sbenno	{ "fctiwz",	0xfc0007fe, 0xfc00001e, Op_D | Op_B | Op_Rc },
36899730Sbenno
36999730Sbenno	{ "fdiv",	0xfc00003e, 0xfc000024, Op_D | Op_A | Op_B | Op_Rc },
37099730Sbenno	{ "fsub",	0xfc00003e, 0xfc000028, Op_D | Op_A | Op_B | Op_Rc },
37199730Sbenno	{ "fadd",	0xfc00003e, 0xfc00002a, Op_D | Op_A | Op_B | Op_Rc },
37299730Sbenno	{ "fsqrt",	0xfc00003e, 0xfc00002c, Op_D | Op_B | Op_Rc },
37399730Sbenno	{ "fsel",	0xfc00003e, 0xfc00002e, Op_D | Op_A | Op_B | Op_C | Op_Rc },
37499730Sbenno	{ "fmul",	0xfc00003e, 0xfc000032, Op_D | Op_A | Op_C | Op_Rc },
37599730Sbenno	{ "frsqrte",	0xfc00003e, 0xfc000034, Op_D | Op_B | Op_Rc },
37699730Sbenno	{ "fmsub",	0xfc00003e, 0xfc000038, Op_D | Op_A | Op_B | Op_C | Op_Rc },
37799730Sbenno	{ "fmadd",	0xfc00003e, 0xfc00003a, Op_D | Op_A | Op_B | Op_C | Op_Rc },
37899730Sbenno	{ "fnmsub",	0xfc00003e, 0xfc00003c, Op_D | Op_A | Op_B | Op_C | Op_Rc },
37999730Sbenno	{ "fnmadd",	0xfc00003e, 0xfc00003e, Op_D | Op_A | Op_B | Op_C | Op_Rc },
38099730Sbenno
38199730Sbenno	{ "fcmpo",	0xfc0007fe, 0xfc000040, Op_crfD | Op_A | Op_B },
38299730Sbenno	{ "mtfsb1",	0xfc0007fe, 0xfc00004c, Op_crfD | Op_Rc },
38399730Sbenno	{ "fneg",	0xfc0007fe, 0xfc000050, Op_D | Op_B | Op_Rc },
38499730Sbenno	{ "mcrfs",	0xfc0007fe, 0xfc000080, Op_D | Op_B | Op_Rc },
38599730Sbenno	{ "mtfsb0",	0xfc0007fe, 0xfc00008c, Op_crfD | Op_Rc },
38699730Sbenno	{ "fmr",	0xfc0007fe, 0xfc000090, Op_D | Op_B | Op_Rc },
38799730Sbenno	{ "mtfsfi",	0xfc0007fe, 0xfc00010c, Op_crfD | Op_IMM | Op_Rc },
38899730Sbenno
38999730Sbenno	{ "fnabs",	0xfc0007fe, 0xfc000110, Op_D | Op_B | Op_Rc },
39099730Sbenno	{ "fabs",	0xfc0007fe, 0xfc000210, Op_D | Op_B | Op_Rc },
39199730Sbenno	{ "mffs",	0xfc0007fe, 0xfc00048e, Op_D | Op_B | Op_Rc },
39299730Sbenno	{ "mtfsf",	0xfc0007fe, 0xfc00058e, Op_FM | Op_B | Op_Rc },
39399730Sbenno	{ "fctid",	0xfc0007fe, 0xfc00065c, Op_D | Op_B | Op_Rc },
39499730Sbenno	{ "fctidz",	0xfc0007fe, 0xfc00065e, Op_D | Op_B | Op_Rc },
39599730Sbenno	{ "fcfid",	0xfc0007fe, 0xfc00069c, Op_D | Op_B | Op_Rc },
39699730Sbenno	{ "",		0x0,		0x0, 0 }
39799730Sbenno};
39899730Sbenno
39999730Sbenno
40099730Sbennostruct specialreg {
40199730Sbenno	int reg;
40299730Sbenno	char *name;
40399730Sbenno};
40499730Sbenno
40599730Sbennoconst struct specialreg sprregs[] = {
40699730Sbenno	{ 0x001, "xer" },
40799730Sbenno	{ 0x008, "lr" },
40899730Sbenno	{ 0x009, "ctr" },
40999730Sbenno	{ 0x012, "dsisr" },
41099730Sbenno	{ 0x013, "dar" },
41199730Sbenno	{ 0x016, "dec" },
41299730Sbenno	{ 0x019, "sdr1" },
41399730Sbenno	{ 0x01a, "srr0" },
41499730Sbenno	{ 0x01b, "srr1" },
41599730Sbenno	{ 0x100, "usprg0" },
41699730Sbenno	{ 0x110, "sprg0" },
41799730Sbenno	{ 0x111, "sprg1" },
41899730Sbenno	{ 0x112, "sprg2" },
41999730Sbenno	{ 0x113, "sprg3" },
42099730Sbenno	{ 0x114, "sprg4" },
42199730Sbenno	{ 0x115, "sprg5" },
42299730Sbenno	{ 0x116, "sprg6" },
42399730Sbenno	{ 0x117, "sprg7" },
42499730Sbenno	{ 0x118, "asr" },
42599730Sbenno	{ 0x11a, "aer" },
42699730Sbenno	{ 0x11c, "tbl" },
42799730Sbenno	{ 0x11d, "tbu" },
42899730Sbenno	{ 0x11f, "pvr" },
42999730Sbenno	{ 0x210, "ibat0u" },
43099730Sbenno	{ 0x211, "ibat0l" },
43199730Sbenno	{ 0x212, "ibat1u" },
43299730Sbenno	{ 0x213, "ibat1l" },
43399730Sbenno	{ 0x214, "ibat2u" },
43499730Sbenno	{ 0x215, "ibat2l" },
43599730Sbenno	{ 0x216, "ibat3u" },
43699730Sbenno	{ 0x217, "ibat3l" },
43799730Sbenno	{ 0x218, "dbat0u" },
43899730Sbenno	{ 0x219, "dbat0l" },
43999730Sbenno	{ 0x21a, "dbat1u" },
44099730Sbenno	{ 0x21b, "dbat1l" },
44199730Sbenno	{ 0x21c, "dbat2u" },
44299730Sbenno	{ 0x21d, "dbat2l" },
44399730Sbenno	{ 0x21e, "dbat3u" },
44499730Sbenno	{ 0x21f, "dbat3l" },
44599730Sbenno	{ 0x3b0, "zpr" },
44699730Sbenno	{ 0x3b1, "pid" },
44799730Sbenno	{ 0x3b3, "ccr0" },
44899730Sbenno	{ 0x3b4, "iac3" },
44999730Sbenno	{ 0x3b5, "iac4" },
45099730Sbenno	{ 0x3b6, "dvc1" },
45199730Sbenno	{ 0x3b7, "dvc2" },
45299730Sbenno	{ 0x3b9, "sgr" },
45399730Sbenno	{ 0x3ba, "dcwr" },
45499730Sbenno	{ 0x3bb, "sler" },
45599730Sbenno	{ 0x3bc, "su0r" },
45699730Sbenno	{ 0x3bd, "dbcr1" },
45799730Sbenno	{ 0x3d3, "icdbdr" },
45899730Sbenno	{ 0x3d4, "esr" },
45999730Sbenno	{ 0x3d5, "dear" },
46099730Sbenno	{ 0x3d6, "evpr" },
46199730Sbenno	{ 0x3d8, "tsr" },
46299730Sbenno	{ 0x3da, "tcr" },
46399730Sbenno	{ 0x3db, "pit" },
46499730Sbenno	{ 0x3de, "srr2" },
46599730Sbenno	{ 0x3df, "srr3" },
46699730Sbenno	{ 0x3f0, "dbsr" },
46799730Sbenno	{ 0x3f2, "dbcr0" },
46899730Sbenno	{ 0x3f4, "iac1" },
46999730Sbenno	{ 0x3f5, "iac2" },
47099730Sbenno	{ 0x3f6, "dac1" },
47199730Sbenno	{ 0x3f7, "dac2" },
47299730Sbenno	{ 0x3f9, "l2cr" },
47399730Sbenno	{ 0x3fa, "dccr" },
47499730Sbenno	{ 0x3fb, "iccr" },
47599730Sbenno	{ 0x3ff, "pir" },
47699730Sbenno	{ 0, NULL }
47799730Sbenno};
47899730Sbenno
47999730Sbennoconst struct specialreg dcrregs[] = {
48099730Sbenno	{ 0x010, "sdram0_cfgaddr" },
48199730Sbenno	{ 0x011, "sdram0_cfgdata" },
48299730Sbenno	{ 0x012, "ebc0_cfgaddr" },
48399730Sbenno	{ 0x013, "ebc0_cfgdata" },
48499730Sbenno	{ 0x014, "dcp0_cfgaddr" },
48599730Sbenno	{ 0x015, "dcp0_cfgdata" },
48699730Sbenno	{ 0x018, "ocm0_isarc" },
48799730Sbenno	{ 0x019, "ocm0_iscntl" },
48899730Sbenno	{ 0x01a, "ocm0_dsarc" },
48999730Sbenno	{ 0x01b, "ocm0_dscntl" },
49099730Sbenno	{ 0x084, "plb0_besr" },
49199730Sbenno	{ 0x086, "plb0_bear" },
49299730Sbenno	{ 0x087, "plb0_acr" },
49399730Sbenno	{ 0x0a0, "pob0_besr0" },
49499730Sbenno	{ 0x0a2, "pob0_bear" },
49599730Sbenno	{ 0x0a4, "pob0_besr1" },
49699730Sbenno	{ 0x0b0, "cpc0_pllmr" },
49799730Sbenno	{ 0x0b1, "cpc0_cr0" },
49899730Sbenno	{ 0x0b2, "cpc0_cr1" },
49999730Sbenno	{ 0x0b4, "cpc0_psr" },
50099730Sbenno	{ 0x0b5, "cpc0_jtagid" },
50199730Sbenno	{ 0x0b8, "cpc0_sr" },
50299730Sbenno	{ 0x0b9, "cpc0_er" },
50399730Sbenno	{ 0x0ba, "cpc0_fr" },
50499730Sbenno	{ 0x0c0, "uic0_sr" },
50599730Sbenno	{ 0x0c2, "uic0_er" },
50699730Sbenno	{ 0x0c3, "uic0_cr" },
50799730Sbenno	{ 0x0c4, "uic0_pr" },
50899730Sbenno	{ 0x0c5, "uic0_tr" },
50999730Sbenno	{ 0x0c6, "uic0_msr" },
51099730Sbenno	{ 0x0c7, "uic0_vr" },
51199730Sbenno	{ 0x0c8, "uic0_vcr" },
51299730Sbenno	{ 0x100, "dma0_cr0" },
51399730Sbenno	{ 0x101, "dma0_ct0" },
51499730Sbenno	{ 0x102, "dma0_da0" },
51599730Sbenno	{ 0x103, "dma0_sa0" },
51699730Sbenno	{ 0x104, "dma0_sg0" },
51799730Sbenno	{ 0x108, "dma0_cr1" },
51899730Sbenno	{ 0x109, "dma0_ct1" },
51999730Sbenno	{ 0x10a, "dma0_da1" },
52099730Sbenno	{ 0x10b, "dma0_sa1" },
52199730Sbenno	{ 0x10c, "dma0_sg1" },
52299730Sbenno	{ 0x110, "dma0_cr2" },
52399730Sbenno	{ 0x111, "dma0_ct2" },
52499730Sbenno	{ 0x112, "dma0_da2" },
52599730Sbenno	{ 0x113, "dma0_sa2" },
52699730Sbenno	{ 0x114, "dma0_sg2" },
52799730Sbenno	{ 0x118, "dma0_cr3" },
52899730Sbenno	{ 0x119, "dma0_ct3" },
52999730Sbenno	{ 0x11a, "dma0_da3" },
53099730Sbenno	{ 0x11b, "dma0_sa3" },
53199730Sbenno	{ 0x11c, "dma0_sg3" },
53299730Sbenno	{ 0x120, "dma0_sr" },
53399730Sbenno	{ 0x123, "dma0_sgc" },
53499730Sbenno	{ 0x125, "dma0_slp" },
53599730Sbenno	{ 0x126, "dma0_pol" },
53699730Sbenno	{ 0x180, "mal0_cfg" },
53799730Sbenno	{ 0x181, "mal0_esr" },
53899730Sbenno	{ 0x182, "mal0_ier" },
53999730Sbenno	{ 0x184, "mal0_txcasr" },
54099730Sbenno	{ 0x185, "mal0_txcarr" },
54199730Sbenno	{ 0x186, "mal0_txeobisr" },
54299730Sbenno	{ 0x187, "mal0_txdeir" },
54399730Sbenno	{ 0x190, "mal0_rxcasr" },
54499730Sbenno	{ 0x191, "mal0_rxcarr" },
54599730Sbenno	{ 0x192, "mal0_rxeobisr" },
54699730Sbenno	{ 0x193, "mal0_rxdeir" },
54799730Sbenno	{ 0x1a0, "mal0_txctp0r" },
54899730Sbenno	{ 0x1a1, "mal0_txctp1r" },
54999730Sbenno	{ 0x1a2, "mal0_txctp2r" },
55099730Sbenno	{ 0x1a3, "mal0_txctp3r" },
55199730Sbenno	{ 0x1c0, "mal0_rxctp0r" },
55299730Sbenno	{ 0x1e0, "mal0_rcbs0" },
55399730Sbenno	{ 0, NULL }
55499730Sbenno};
55599730Sbenno
55699730Sbennovoid
55799730Sbennoop_ill(instr_t instr, vm_offset_t loc)
55899730Sbenno{
55999730Sbenno	db_printf("illegal instruction %x\n", instr);
56099730Sbenno}
56199730Sbenno
56299730Sbennou_int32_t
56399730Sbennoextract_field(u_int32_t value, u_int32_t base, u_int32_t width)
56499730Sbenno{
56599730Sbenno	u_int32_t mask = (1 << width) - 1;
56699730Sbenno	return ((value >> base) & mask);
56799730Sbenno}
56899730Sbenno
56999730Sbennoconst struct opcode * search_op(const struct opcode *);
57099730Sbenno
57199730Sbennovoid
57299730Sbennodisasm_fields(const struct opcode *popcode, instr_t instr, vm_offset_t loc,
57399730Sbenno	char *disasm_str)
57499730Sbenno{
57599730Sbenno	char * pstr;
57699730Sbenno	enum function_mask func;
57799730Sbenno
57899730Sbenno	pstr = disasm_str;
57999730Sbenno
58099730Sbenno	func =  popcode->func;
58199730Sbenno	if (func & Op_OE) {
58299730Sbenno		u_int OE;
58399730Sbenno		/* also for Op_S (they are the same) */
58499730Sbenno		OE = extract_field(instr, 31 - 21, 1);
58599730Sbenno		if (OE) {
58699730Sbenno			pstr += sprintf(pstr, "o");
58799730Sbenno		}
58899730Sbenno		func &= ~Op_OE;
58999730Sbenno	}
59099730Sbenno	switch (func & Op_LKM) {
59199730Sbenno	case Op_Rc:
59299730Sbenno		if (instr & 0x1) {
59399730Sbenno			pstr += sprintf(pstr, ".");
59499730Sbenno		}
59599730Sbenno		break;
59699730Sbenno	case Op_AA:
59799730Sbenno		if (instr & 0x2) {
59899730Sbenno			pstr += sprintf(pstr, "a");
59999730Sbenno			loc = 0; /* Absolute address */
60099730Sbenno		}
60199730Sbenno	case Op_LK:
60299730Sbenno		if (instr & 0x1) {
60399730Sbenno			pstr += sprintf(pstr, "l");
60499730Sbenno		}
60599730Sbenno		break;
60699730Sbenno	default:
60799730Sbenno		func &= ~Op_LKM;
60899730Sbenno	}
60999730Sbenno	pstr += sprintf(pstr, "\t");
61099730Sbenno
61199730Sbenno	/* XXX: special cases here, out of flags in a 32bit word. */
61299730Sbenno	if (strcmp(popcode->name, "wrteei") == 0) {
61399730Sbenno		int E;
61499730Sbenno		E = extract_field(instr, 31 - 16, 5);
61599730Sbenno		pstr += sprintf(pstr, "%d", E);
61699730Sbenno		return;
61799730Sbenno	}
61899730Sbenno	/* XXX: end of special cases here. */
61999730Sbenno
62099730Sbenno	if (func & Op_D) {
62199730Sbenno		u_int D;
62299730Sbenno		/* also for Op_S (they are the same) */
62399730Sbenno		D = extract_field(instr, 31 - 10, 5);
62499730Sbenno		pstr += sprintf(pstr, "r%d, ", D);
62599730Sbenno		func &= ~Op_D;
62699730Sbenno	}
62799730Sbenno	if (func & Op_crbD) {
62899730Sbenno		u_int crbD;
62999730Sbenno		crbD = extract_field(instr, 31 - 10, 5);
63099730Sbenno		pstr += sprintf(pstr, "crb%d, ", crbD);
63199730Sbenno		func &= ~Op_crbD;
63299730Sbenno	}
63399730Sbenno	if (func & Op_crfD) {
63499730Sbenno		u_int crfD;
63599730Sbenno		crfD = extract_field(instr, 31 - 8, 3);
63699730Sbenno		pstr += sprintf(pstr, "crf%d, ", crfD);
63799730Sbenno		func &= ~Op_crfD;
63899730Sbenno	}
63999730Sbenno	if (func & Op_L) {
64099730Sbenno		u_int L;
64199730Sbenno		L = extract_field(instr, 31 - 10, 1);
64299730Sbenno		if (L) {
64399730Sbenno			pstr += sprintf(pstr, "L, ");
64499730Sbenno		}
64599730Sbenno		func &= ~Op_L;
64699730Sbenno	}
64799730Sbenno	if (func & Op_FM) {
64899730Sbenno		u_int FM;
64999730Sbenno		FM = extract_field(instr, 31 - 10, 8);
65099730Sbenno		pstr += sprintf(pstr, "%d, ", FM);
65199730Sbenno		func &= ~Op_FM;
65299730Sbenno	}
65399730Sbenno	if (func & Op_TO) {
65499730Sbenno		u_int TO;
65599730Sbenno		TO = extract_field(instr, 31 - 10, 1);
65699730Sbenno		pstr += sprintf(pstr, "%d, ", TO);
65799730Sbenno		func &= ~Op_TO;
65899730Sbenno	}
65999730Sbenno	if (func & Op_crfS) {
66099730Sbenno		u_int crfS;
66199730Sbenno		crfS = extract_field(instr, 31 - 13, 3);
66299730Sbenno		pstr += sprintf(pstr, "%d, ", crfS);
66399730Sbenno		func &= ~Op_crfS;
66499730Sbenno	}
66599730Sbenno	if (func & Op_BO) {
66699730Sbenno		u_int BO;
66799730Sbenno		BO = extract_field(instr, 31 - 10, 5);
66899730Sbenno		pstr += sprintf(pstr, "%d, ", BO);
66999730Sbenno		func &= ~Op_BO;
67099730Sbenno	}
67199730Sbenno	if (func & Op_A) {
67299730Sbenno		u_int A;
67399730Sbenno		A = extract_field(instr, 31 - 15, 5);
67499730Sbenno		pstr += sprintf(pstr, "r%d, ", A);
67599730Sbenno		func &= ~Op_A;
67699730Sbenno	}
67799730Sbenno	if (func & Op_B) {
67899730Sbenno		u_int B;
67999730Sbenno		B = extract_field(instr, 31 - 20, 5);
68099730Sbenno		pstr += sprintf(pstr, "r%d, ", B);
68199730Sbenno		func &= ~Op_B;
68299730Sbenno	}
68399730Sbenno	if (func & Op_C) {
68499730Sbenno		u_int C;
68599730Sbenno		C = extract_field(instr, 31 - 25, 5);
68699730Sbenno		pstr += sprintf(pstr, "r%d, ", C);
68799730Sbenno		func &= ~Op_C;
68899730Sbenno	}
68999730Sbenno	if (func & Op_BI) {
69099730Sbenno		u_int BI;
69199730Sbenno		BI = extract_field(instr, 31 - 10, 5);
69299730Sbenno		pstr += sprintf(pstr, "%d, ", BI);
69399730Sbenno		func &= ~Op_BI;
69499730Sbenno	}
69599730Sbenno	if (func & Op_crbA) {
69699730Sbenno		u_int crbA;
69799730Sbenno		crbA = extract_field(instr, 31 - 15, 5);
69899730Sbenno		pstr += sprintf(pstr, "%d, ", crbA);
69999730Sbenno		func &= ~Op_crbA;
70099730Sbenno	}
70199730Sbenno	if (func & Op_crbB) {
70299730Sbenno		u_int crbB;
70399730Sbenno		crbB = extract_field(instr, 31 - 20, 5);
70499730Sbenno		pstr += sprintf(pstr, "%d, ", crbB);
70599730Sbenno		func &= ~Op_crbB;
70699730Sbenno	}
70799730Sbenno	if (func & Op_CRM) {
70899730Sbenno		u_int CRM;
70999730Sbenno		CRM = extract_field(instr, 31 - 19, 8);
71099730Sbenno		pstr += sprintf(pstr, "0x%x, ", CRM);
71199730Sbenno		func &= ~Op_CRM;
71299730Sbenno	}
71399730Sbenno	if (func & Op_LI) {
71499730Sbenno		int LI;
71599730Sbenno		LI = extract_field(instr, 31 - 29, 24);
71699730Sbenno		/* Need to sign extend and shift up 2, then add addr */
71799730Sbenno		LI = LI << 8;
71899730Sbenno		LI = LI >> 6;
71999730Sbenno		LI += loc;
720104435Sgrehan		pstr += sprintf (pstr, "0x%x, ", LI);
72199730Sbenno		func &= ~Op_LI;
72299730Sbenno	}
72399730Sbenno	switch (func & Op_SIMM) {
72499730Sbenno		u_int IMM;
72599730Sbenno	case Op_SIMM: /* same as Op_d */
72699730Sbenno		IMM = extract_field(instr, 31 - 31, 16);
72799730Sbenno		if (IMM & 0x8000) {
72899730Sbenno			pstr += sprintf(pstr, "-");
72999730Sbenno			IMM = 0x10000-IMM;
73099730Sbenno		}
73199730Sbenno		func &= ~Op_SIMM;
73299730Sbenno		goto common;
73399730Sbenno	case Op_UIMM:
73499730Sbenno		IMM = extract_field(instr, 31 - 31, 16);
73599730Sbenno		func &= ~Op_UIMM;
73699730Sbenno		goto common;
73799730Sbenno	common:
73899730Sbenno		pstr += sprintf(pstr, "0x%x", IMM);
73999730Sbenno		break;
74099730Sbenno	default:
741104435Sgrehan		break;
74299730Sbenno	}
74399730Sbenno	if (func & Op_BD) {
74499730Sbenno		u_int BD;
74599730Sbenno		BD = extract_field(instr, 31 - 29, 14);
74699730Sbenno		pstr += sprintf(pstr, "0x%x, ", BD);
74799730Sbenno		func &= ~Op_BD;
74899730Sbenno	}
74999730Sbenno	if (func & Op_ds) {
75099730Sbenno		u_int ds;
75199730Sbenno		ds = extract_field(instr, 31 - 29, 14) << 2;
75299730Sbenno		pstr += sprintf(pstr, "0x%x, ", ds);
75399730Sbenno		func &= ~Op_ds;
75499730Sbenno	}
75599730Sbenno	if (func & Op_spr) {
75699730Sbenno		u_int spr;
75799730Sbenno		u_int sprl;
75899730Sbenno		u_int sprh;
75999730Sbenno		const struct specialreg *regs;
76099730Sbenno		int i;
76199730Sbenno		sprl = extract_field(instr, 31 - 15, 5);
76299730Sbenno		sprh = extract_field(instr, 31 - 20, 5);
76399730Sbenno		spr = sprh << 5 | sprl;
76499730Sbenno
76599730Sbenno		/* ugly hack - out of bitfields in the function mask */
76699730Sbenno		if (popcode->name[2] == 'd')	/* m.Dcr */
76799730Sbenno			regs = dcrregs;
76899730Sbenno		else
76999730Sbenno			regs = sprregs;
77099730Sbenno		for (i = 0; regs[i].name != NULL; i++)
77199730Sbenno			if (spr == regs[i].reg)
77299730Sbenno				break;
77399730Sbenno		if (regs[i].reg == 0)
77499730Sbenno			pstr += sprintf(pstr, "[unknown special reg (%d)]", spr);
77599730Sbenno		else
77699730Sbenno			pstr += sprintf(pstr, "%s", regs[i].name);
77799730Sbenno		func &= ~Op_spr;
77899730Sbenno	}
77999730Sbenno
78099730Sbenno	if (func & Op_me) {
78199730Sbenno		u_int me, mel, meh;
78299730Sbenno		mel = extract_field(instr, 31 - 25, 4);
78399730Sbenno		meh = extract_field(instr, 31 - 26, 1);
78499730Sbenno		me = meh << 4 | mel;
78599730Sbenno		pstr += sprintf(pstr, ", 0x%x", me);
78699730Sbenno		func &= ~Op_me;
78799730Sbenno	}
78899730Sbenno	if ((func & Op_MB) && (func & Op_sh_mb_sh)) {
78999730Sbenno		u_int MB;
79099730Sbenno		u_int ME;
79199730Sbenno		MB = extract_field(instr, 31 - 20, 5);
79299730Sbenno		pstr += sprintf(pstr, ", %d", MB);
79399730Sbenno		ME = extract_field(instr, 31 - 25, 5);
79499730Sbenno		pstr += sprintf(pstr, ", %d", ME);
79599730Sbenno	}
79699730Sbenno	if ((func & Op_SH) && (func & Op_sh_mb_sh)) {
79799730Sbenno		u_int SH;
79899730Sbenno		SH = extract_field(instr, 31 - 20, 5);
79999730Sbenno		pstr += sprintf(pstr, ", %d", SH);
80099730Sbenno	}
80199730Sbenno	if ((func & Op_sh) && ! (func & Op_sh_mb_sh)) {
80299730Sbenno		u_int sh, shl, shh;
80399730Sbenno		shl = extract_field(instr, 31 - 19, 4);
80499730Sbenno		shh = extract_field(instr, 31 - 20, 1);
80599730Sbenno		sh = shh << 4 | shl;
80699730Sbenno		pstr += sprintf(pstr, ", %d", sh);
80799730Sbenno	}
80899730Sbenno	if ((func & Op_mb) && ! (func & Op_sh_mb_sh)) {
80999730Sbenno		u_int mb, mbl, mbh;
81099730Sbenno		mbl = extract_field(instr, 31 - 25, 4);
81199730Sbenno		mbh = extract_field(instr, 31 - 26, 1);
81299730Sbenno		mb = mbh << 4 | mbl;
81399730Sbenno		pstr += sprintf(pstr, ", %d", mb);
81499730Sbenno	}
81599730Sbenno	if ((func & Op_me) && ! (func & Op_sh_mb_sh)) {
81699730Sbenno		u_int me, mel, meh;
81799730Sbenno		mel = extract_field(instr, 31 - 25, 4);
81899730Sbenno		meh = extract_field(instr, 31 - 26, 1);
81999730Sbenno		me = meh << 4 | mel;
82099730Sbenno		pstr += sprintf(pstr, ", %d", me);
82199730Sbenno	}
82299730Sbenno	if (func & Op_tbr) {
82399730Sbenno		u_int tbr;
82499730Sbenno		u_int tbrl;
82599730Sbenno		u_int tbrh;
82699730Sbenno		char *reg;
82799730Sbenno		tbrl = extract_field(instr, 31 - 15, 5);
82899730Sbenno		tbrh = extract_field(instr, 31 - 20, 5);
82999730Sbenno		tbr = tbrh << 5 | tbrl;
83099730Sbenno
83199730Sbenno		switch (tbr) {
83299730Sbenno		case 268:
83399730Sbenno			reg = "tbl";
83499730Sbenno			break;
83599730Sbenno		case 269:
83699730Sbenno			reg = "tbu";
83799730Sbenno			break;
83899730Sbenno		default:
83999730Sbenno			reg = 0;
84099730Sbenno		}
84199730Sbenno		if (reg == 0)
84299730Sbenno			pstr += sprintf(pstr, ", [unknown tbr %d ]", tbr);
84399730Sbenno		else
84499730Sbenno			pstr += sprintf(pstr, ", %s", reg);
84599730Sbenno		func &= ~Op_tbr;
84699730Sbenno	}
84799730Sbenno	if (func & Op_SR) {
84899730Sbenno		u_int SR;
84999730Sbenno		SR = extract_field(instr, 31 - 15, 3);
85099730Sbenno		pstr += sprintf(pstr, ", sr%d", SR);
85199730Sbenno		func &= ~Op_SR;
85299730Sbenno	}
85399730Sbenno	if (func & Op_NB) {
85499730Sbenno		u_int NB;
85599730Sbenno		NB = extract_field(instr, 31 - 20, 5);
85699730Sbenno		if (NB == 0)
85799730Sbenno			NB = 32;
85899730Sbenno		pstr += sprintf(pstr, ", %d", NB);
85999730Sbenno		func &= ~Op_SR;
86099730Sbenno	}
86199730Sbenno	if (func & Op_IMM) {
86299730Sbenno		u_int IMM;
86399730Sbenno		IMM = extract_field(instr, 31 - 19, 4);
86499730Sbenno		pstr += sprintf(pstr, ", %d", IMM);
86599730Sbenno		func &= ~Op_SR;
86699730Sbenno	}
86799730Sbenno}
86899730Sbenno
86999730Sbennovoid
87099730Sbennoop_base(instr_t instr, vm_offset_t loc)
87199730Sbenno{
87299730Sbenno	dis_ppc(opcodes, instr, loc);
87399730Sbenno}
87499730Sbenno
87599730Sbennovoid
87699730Sbennoop_cl_x13(instr_t instr, vm_offset_t loc)
87799730Sbenno{
87899730Sbenno	dis_ppc(opcodes_13, instr, loc);
87999730Sbenno}
88099730Sbenno
88199730Sbennovoid
88299730Sbennoop_cl_x1e(instr_t instr, vm_offset_t loc)
88399730Sbenno{
88499730Sbenno	dis_ppc(opcodes_1e, instr, loc);
88599730Sbenno}
88699730Sbenno
88799730Sbennovoid
88899730Sbennoop_cl_x1f(instr_t instr, vm_offset_t loc)
88999730Sbenno{
89099730Sbenno	dis_ppc(opcodes_1f, instr, loc);
89199730Sbenno}
89299730Sbenno
89399730Sbennovoid
89499730Sbennoop_cl_x3a(instr_t instr, vm_offset_t loc)
89599730Sbenno{
89699730Sbenno	dis_ppc(opcodes_3a, instr, loc);
89799730Sbenno}
89899730Sbenno
89999730Sbennovoid
90099730Sbennoop_cl_x3b(instr_t instr, vm_offset_t loc)
90199730Sbenno{
90299730Sbenno	dis_ppc(opcodes_3b, instr, loc);
90399730Sbenno}
90499730Sbenno
90599730Sbennovoid
90699730Sbennoop_cl_x3e(instr_t instr, vm_offset_t loc)
90799730Sbenno{
90899730Sbenno	dis_ppc(opcodes_3e, instr, loc);
90999730Sbenno}
91099730Sbenno
91199730Sbennovoid
91299730Sbennoop_cl_x3f(instr_t instr, vm_offset_t loc)
91399730Sbenno{
91499730Sbenno	dis_ppc(opcodes_3f, instr, loc);
91599730Sbenno}
91699730Sbenno
91799730Sbennovoid
91899730Sbennodis_ppc(const struct opcode *opcodeset, instr_t instr, vm_offset_t loc)
91999730Sbenno{
92099730Sbenno	const struct opcode *op;
92199730Sbenno	int found = 0;
92299730Sbenno	int i;
92399730Sbenno	char disasm_str[30];
92499730Sbenno
92599730Sbenno	for (i = 0, op = &opcodeset[0];
92699730Sbenno	    found == 0 && op->mask != 0;
92799730Sbenno	    i++, op = &opcodeset[i]) {
92899730Sbenno		if ((instr & op->mask) == op->code) {
92999730Sbenno			found = 1;
93099730Sbenno			disasm_fields(op, instr, loc, disasm_str);
93199730Sbenno			db_printf("%s%s\n", op->name, disasm_str);
93299730Sbenno			return;
93399730Sbenno		}
93499730Sbenno	}
93599730Sbenno	op_ill(instr, loc);
93699730Sbenno}
93799730Sbenno
93899730Sbennodb_addr_t
93999730Sbennodb_disasm(db_addr_t loc, boolean_t extended)
94099730Sbenno{
94199730Sbenno	int class;
94299730Sbenno	instr_t opcode;
94399730Sbenno	opcode = *(instr_t *)(loc);
94499730Sbenno	class = opcode >> 26;
94599730Sbenno	(opcodes_base[class])(opcode, loc);
94699730Sbenno
94799730Sbenno	return (loc + 4);
94899730Sbenno}
94999730Sbenno
95099730Sbennovm_offset_t opc_disasm(vm_offset_t loc, int);
95199730Sbenno
95299730Sbennovm_offset_t
95399730Sbennoopc_disasm(vm_offset_t loc, int xin)
95499730Sbenno{
95599730Sbenno	int class;
95699730Sbenno	instr_t opcode;
95799730Sbenno	opcode = xin;
95899730Sbenno	class = opcode >> 26;
95999730Sbenno	(opcodes_base[class])(opcode, loc);
96099730Sbenno
96199730Sbenno	return (loc + 4);
96299730Sbenno}
963