static void print_sh_insn()

in kernel/disassemble.c [291:545]


static void print_sh_insn(u32 memaddr, u16 insn)
{
	int relmask = ~0;
	int nibs[4] = { (insn >> 12) & 0xf, (insn >> 8) & 0xf, (insn >> 4) & 0xf, insn & 0xf};
	int lastsp;
	struct sh_opcode_info *op = sh_table;

	for (; op->name; op++) {
		int n;
		int imm = 0;
		int rn = 0;
		int rm = 0;
		int rb = 0;
		int disp_pc;
		int disp_pc_addr = 0;

		for (n = 0; n < 4; n++) {
			int i = op->nibbles[n];

			if (i < 16) {
				if (nibs[n] == i)
					continue;
				goto fail;
			}
			switch (i) {
			case BRANCH_8:
				imm = (nibs[2] << 4) | (nibs[3]);
				if (imm & 0x80)
					imm |= ~0xff;
				imm = ((char)imm) * 2 + 4 ;
				goto ok;
			case BRANCH_12:
				imm = ((nibs[1]) << 8) | (nibs[2] << 4) | (nibs[3]);
				if (imm & 0x800)
					imm |= ~0xfff;
				imm = imm * 2 + 4;
				goto ok;
			case IMM_4:
				imm = nibs[3];
				goto ok;
			case IMM_4BY2:
				imm = nibs[3] <<1;
				goto ok;
			case IMM_4BY4:
				imm = nibs[3] <<2;
				goto ok;
			case IMM_8:
				imm = (nibs[2] << 4) | nibs[3];
				goto ok;
			case PCRELIMM_8BY2:
				imm = ((nibs[2] << 4) | nibs[3]) <<1;
				relmask = ~1;
				goto ok;
			case PCRELIMM_8BY4:
				imm = ((nibs[2] << 4) | nibs[3]) <<2;
				relmask = ~3;
				goto ok;
			case IMM_8BY2:
				imm = ((nibs[2] << 4) | nibs[3]) <<1;
				goto ok;
			case IMM_8BY4:
				imm = ((nibs[2] << 4) | nibs[3]) <<2;
				goto ok;
			case DISP_8:
				imm = (nibs[2] << 4) | (nibs[3]);
				goto ok;
			case DISP_4:
				imm = nibs[3];
				goto ok;
			case REG_N:
				rn = nibs[n];
				break;
			case REG_M:
				rm = nibs[n];
				break;
			case REG_NM:
				rn = (nibs[n] & 0xc) >> 2;
				rm = (nibs[n] & 0x3);
				break;
			case REG_B:
				rb = nibs[n] & 0x07;
				break;
			default:
				return;
			}
		}

	ok:
		pr_cont("%-8s  ", op->name);
		lastsp = (op->arg[0] == A_END);
		disp_pc = 0;
		for (n = 0; n < 6 && op->arg[n] != A_END; n++) {
			if (n && op->arg[1] != A_END)
				pr_cont(", ");
			switch (op->arg[n]) {
			case A_IMM:
				pr_cont("#%d", (char)(imm));
				break;
			case A_R0:
				pr_cont("r0");
				break;
			case A_REG_N:
				pr_cont("r%d", rn);
				break;
			case A_INC_N:
				pr_cont("@r%d+", rn);
				break;
			case A_DEC_N:
				pr_cont("@-r%d", rn);
				break;
			case A_IND_N:
				pr_cont("@r%d", rn);
				break;
			case A_DISP_REG_N:
				pr_cont("@(%d,r%d)", imm, rn);
				break;
			case A_REG_M:
				pr_cont("r%d", rm);
				break;
			case A_INC_M:
				pr_cont("@r%d+", rm);
				break;
			case A_DEC_M:
				pr_cont("@-r%d", rm);
				break;
			case A_IND_M:
				pr_cont("@r%d", rm);
				break;
			case A_DISP_REG_M:
				pr_cont("@(%d,r%d)", imm, rm);
				break;
			case A_REG_B:
				pr_cont("r%d_bank", rb);
				break;
			case A_DISP_PC:
				disp_pc = 1;
				disp_pc_addr = imm + 4 + (memaddr & relmask);
				pr_cont("%08x <%pS>", disp_pc_addr,
					(void *)disp_pc_addr);
				break;
			case A_IND_R0_REG_N:
				pr_cont("@(r0,r%d)", rn);
				break;
			case A_IND_R0_REG_M:
				pr_cont("@(r0,r%d)", rm);
				break;
			case A_DISP_GBR:
				pr_cont("@(%d,gbr)", imm);
				break;
			case A_R0_GBR:
				pr_cont("@(r0,gbr)");
				break;
			case A_BDISP12:
			case A_BDISP8:
				pr_cont("%08x", imm + memaddr);
				break;
			case A_SR:
				pr_cont("sr");
				break;
			case A_GBR:
				pr_cont("gbr");
				break;
			case A_VBR:
				pr_cont("vbr");
				break;
			case A_SSR:
				pr_cont("ssr");
				break;
			case A_SPC:
				pr_cont("spc");
				break;
			case A_MACH:
				pr_cont("mach");
				break;
			case A_MACL:
				pr_cont("macl");
				break;
			case A_PR:
				pr_cont("pr");
				break;
			case A_SGR:
				pr_cont("sgr");
				break;
			case A_DBR:
				pr_cont("dbr");
				break;
			case FD_REG_N:
			case F_REG_N:
				pr_cont("fr%d", rn);
				break;
			case F_REG_M:
				pr_cont("fr%d", rm);
				break;
			case DX_REG_N:
				if (rn & 1) {
					pr_cont("xd%d", rn & ~1);
					break;
				}
				fallthrough;
			case D_REG_N:
				pr_cont("dr%d", rn);
				break;
			case DX_REG_M:
				if (rm & 1) {
					pr_cont("xd%d", rm & ~1);
					break;
				}
				fallthrough;
			case D_REG_M:
				pr_cont("dr%d", rm);
				break;
			case FPSCR_M:
			case FPSCR_N:
				pr_cont("fpscr");
				break;
			case FPUL_M:
			case FPUL_N:
				pr_cont("fpul");
				break;
			case F_FR0:
				pr_cont("fr0");
				break;
			case V_REG_N:
				pr_cont("fv%d", rn*4);
				break;
			case V_REG_M:
				pr_cont("fv%d", rm*4);
				break;
			case XMTRX_M4:
				pr_cont("xmtrx");
				break;
			default:
				return;
			}
		}

		if (disp_pc && strcmp(op->name, "mova") != 0) {
			u32 val;

			if (relmask == ~1)
				__get_user(val, (u16 *)disp_pc_addr);
			else
				__get_user(val, (u32 *)disp_pc_addr);

			pr_cont("  ! %08x <%pS>", val, (void *)val);
		}

		return;
	fail:
		;

	}

	pr_info(".word 0x%x%x%x%x", nibs[0], nibs[1], nibs[2], nibs[3]);
}