/*
 * several functions that help interpret ARC instructions
 * used for unaligned accesses, kprobes and kgdb
 *
 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/types.h>
#include <linux/kprobes.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <asm/disasm.h>

#if defined(CONFIG_KGDB) || defined(CONFIG_ARC_EMUL_UNALIGNED) || \
	defined(CONFIG_KPROBES)

/* disasm_instr: Analyses instruction at addr, stores
 * findings in *state
 */
void __kprobes disasm_instr(unsigned long addr, struct disasm_state *state,
	int userspace, struct pt_regs *regs, struct callee_regs *cregs)
{
	int fieldA = 0;
	int fieldC = 0, fieldCisReg = 0;
	uint16_t word1 = 0, word0 = 0;
	int subopcode, is_linked, op_format;
	uint16_t *ins_ptr;
	uint16_t ins_buf[4];
	int bytes_not_copied = 0;

	memset(state, 0, sizeof(struct disasm_state));

	/* This fetches the upper part of the 32 bit instruction
	 * in both the cases of Little Endian or Big Endian configurations. */
	if (userspace) {
		bytes_not_copied = copy_from_user(ins_buf,
						(const void __user *) addr, 8);
		if (bytes_not_copied > 6)
			goto fault;
		ins_ptr = ins_buf;
	} else {
		ins_ptr = (uint16_t *) addr;
	}

	word1 = *((uint16_t *)addr);

	state->major_opcode = (word1 >> 11) & 0x1F;

	/* Check if the instruction is 32 bit or 16 bit instruction */
	if (state->major_opcode < 0x0B) {
		if (bytes_not_copied > 4)
			goto fault;
		state->instr_len = 4;
		word0 = *((uint16_t *)(addr+2));
		state->words[0] = (word1 << 16) | word0;
	} else {
		state->instr_len = 2;
		state->words[0] = word1;
	}

	/* Read the second word in case of limm */
	word1 = *((uint16_t *)(addr + state->instr_len));
	word0 = *((uint16_t *)(addr + state->instr_len + 2));
	state->words[1] = (word1 << 16) | word0;

	switch (state->major_opcode) {
	case op_Bcc:
		state->is_branch = 1;

		/* unconditional branch s25, conditional branch s21 */
		fieldA = (IS_BIT(state->words[0], 16)) ?
			FIELD_s25(state->words[0]) :
			FIELD_s21(state->words[0]);

		state->delay_slot = IS_BIT(state->words[0], 5);
		state->target = fieldA + (addr & ~0x3);
		state->flow = direct_jump;
		break;

	case op_BLcc:
		if (IS_BIT(state->words[0], 16)) {
			/* Branch and Link*/
			/* unconditional branch s25, conditional branch s21 */
			fieldA = (IS_BIT(state->words[0], 17)) ?
				(FIELD_s25(state->words[0]) & ~0x3) :
				FIELD_s21(state->words[0]);

			state->flow = direct_call;
		} else {
			/*Branch On Compare */
			fieldA = FIELD_s9(state->words[0]) & ~0x3;
			state->flow = direct_jump;
		}

		state->delay_slot = IS_BIT(state->words[0], 5);
		state->target = fieldA + (addr & ~0x3);
		state->is_branch = 1;
		break;

	case op_LD:  /* LD<zz> a,[b,s9] */
		state->write = 0;
		state->di = BITS(state->words[0], 11, 11);
		if (state->di)
			break;
		state->x = BITS(state->words[0], 6, 6);
		state->zz = BITS(state->words[0], 7, 8);
		state->aa = BITS(state->words[0], 9, 10);
		state->wb_reg = FIELD_B(state->words[0]);
		if (state->wb_reg == REG_LIMM) {
			state->instr_len += 4;
			state->aa = 0;
			state->src1 = state->words[1];
		} else {
			state->src1 = get_reg(state->wb_reg, regs, cregs);
		}
		state->src2 = FIELD_s9(state->words[0]);
		state->dest = FIELD_A(state->words[0]);
		state->pref = (state->dest == REG_LIMM);
		break;

	case op_ST:
		state->write = 1;
		state->di = BITS(state->words[0], 5, 5);
		if (state->di)
			break;
		state->aa = BITS(state->words[0], 3, 4);
		state->zz = BITS(state->words[0], 1, 2);
		state->src1 = FIELD_C(state->words[0]);
		if (state->src1 == REG_LIMM) {
			state->instr_len += 4;
			state->src1 = state->words[1];
		} else {
			state->src1 = get_reg(state->src1, regs, cregs);
		}
		state->wb_reg = FIELD_B(state->words[0]);
		if (state->wb_reg == REG_LIMM) {
			state->aa = 0;
			state->instr_len += 4;
			state->src2 = state->words[1];
		} else {
			state->src2 = get_reg(state->wb_reg, regs, cregs);
		}
		state->src3 = FIELD_s9(state->words[0]);
		break;

	case op_MAJOR_4:
		subopcode = MINOR_OPCODE(state->words[0]);
		switch (subopcode) {
		case 32:	/* Jcc */
		case 33:	/* Jcc.D */
		case 34:	/* JLcc */
		case 35:	/* JLcc.D */
			is_linked = 0;

			if (subopcode == 33 || subopcode == 35)
				state->delay_slot = 1;

			if (subopcode == 34 || subopcode == 35)
				is_linked = 1;

			fieldCisReg = 0;
			op_format = BITS(state->words[0], 22, 23);
			if (op_format == 0 || ((op_format == 3) &&
				(!IS_BIT(state->words[0], 5)))) {
				fieldC = FIELD_C(state->words[0]);

				if (fieldC == REG_LIMM) {
					fieldC = state->words[1];
					state->instr_len += 4;
				} else {
					fieldCisReg = 1;
				}
			} else if (op_format == 1 || ((op_format == 3)
				&& (IS_BIT(state->words[0], 5)))) {
				fieldC = FIELD_C(state->words[0]);
			} else  {
				/* op_format == 2 */
				fieldC = FIELD_s12(state->words[0]);
			}

			if (!fieldCisReg) {
				state->target = fieldC;
				state->flow = is_linked ?
					direct_call : direct_jump;
			} else {
				state->target = get_reg(fieldC, regs, cregs);
				state->flow = is_linked ?
					indirect_call : indirect_jump;
			}
			state->is_branch = 1;
			break;

		case 40:	/* LPcc */
			if (BITS(state->words[0], 22, 23) == 3) {
				/* Conditional LPcc u7 */
				fieldC = FIELD_C(state->words[0]);

				fieldC = fieldC << 1;
				fieldC += (addr & ~0x03);
				state->is_branch = 1;
				state->flow = direct_jump;
				state->target = fieldC;
			}
			/* For Unconditional lp, next pc is the fall through
			 * which is updated */
			break;

		case 48 ... 55:	/* LD a,[b,c] */
			state->di = BITS(state->words[0], 15, 15);
			if (state->di)
				break;
			state->x = BITS(state->words[0], 16, 16);
			state->zz = BITS(state->words[0], 17, 18);
			state->aa = BITS(state->words[0], 22, 23);
			state->wb_reg = FIELD_B(state->words[0]);
			if (state->wb_reg == REG_LIMM) {
				state->instr_len += 4;
				state->src1 = state->words[1];
			} else {
				state->src1 = get_reg(state->wb_reg, regs,
						cregs);
			}
			state->src2 = FIELD_C(state->words[0]);
			if (state->src2 == REG_LIMM) {
				state->instr_len += 4;
				state->src2 = state->words[1];
			} else {
				state->src2 = get_reg(state->src2, regs,
					cregs);
			}
			state->dest = FIELD_A(state->words[0]);
			if (state->dest == REG_LIMM)
				state->pref = 1;
			break;

		case 10:	/* MOV */
			/* still need to check for limm to extract instr len */
			/* MOV is special case because it only takes 2 args */
			switch (BITS(state->words[0], 22, 23)) {
			case 0: /* OP a,b,c */
				if (FIELD_C(state->words[0]) == REG_LIMM)
					state->instr_len += 4;
				break;
			case 1: /* OP a,b,u6 */
				break;
			case 2: /* OP b,b,s12 */
				break;
			case 3: /* OP.cc b,b,c/u6 */
				if ((!IS_BIT(state->words[0], 5)) &&
				    (FIELD_C(state->words[0]) == REG_LIMM))
					state->instr_len += 4;
				break;
			}
			break;


		default:
			/* Not a Load, Jump or Loop instruction */
			/* still need to check for limm to extract instr len */
			switch (BITS(state->words[0], 22, 23)) {
			case 0: /* OP a,b,c */
				if ((FIELD_B(state->words[0]) == REG_LIMM) ||
				    (FIELD_C(state->words[0]) == REG_LIMM))
					state->instr_len += 4;
				break;
			case 1: /* OP a,b,u6 */
				break;
			case 2: /* OP b,b,s12 */
				break;
			case 3: /* OP.cc b,b,c/u6 */
				if ((!IS_BIT(state->words[0], 5)) &&
				   ((FIELD_B(state->words[0]) == REG_LIMM) ||
				    (FIELD_C(state->words[0]) == REG_LIMM)))
					state->instr_len += 4;
				break;
			}
			break;
		}
		break;

	/* 16 Bit Instructions */
	case op_LD_ADD: /* LD_S|LDB_S|LDW_S a,[b,c] */
		state->zz = BITS(state->words[0], 3, 4);
		state->src1 = get_reg(FIELD_S_B(state->words[0]), regs, cregs);
		state->src2 = get_reg(FIELD_S_C(state->words[0]), regs, cregs);
		state->dest = FIELD_S_A(state->words[0]);
		break;

	case op_ADD_MOV_CMP:
		/* check for limm, ignore mov_s h,b (== mov_s 0,b) */
		if ((BITS(state->words[0], 3, 4) < 3) &&
		    (FIELD_S_H(state->words[0]) == REG_LIMM))
			state->instr_len += 4;
		break;

	case op_S:
		subopcode = BITS(state->words[0], 5, 7);
		switch (subopcode) {
		case 0:	/* j_s */
		case 1:	/* j_s.d */
		case 2:	/* jl_s */
		case 3:	/* jl_s.d */
			state->target = get_reg(FIELD_S_B(state->words[0]),
						regs, cregs);
			state->delay_slot = subopcode & 1;
			state->flow = (subopcode >= 2) ?
				direct_call : indirect_jump;
			break;
		case 7:
			switch (BITS(state->words[0], 8, 10)) {
			case 4:	/* jeq_s [blink] */
			case 5:	/* jne_s [blink] */
			case 6:	/* j_s [blink] */
			case 7:	/* j_s.d [blink] */
				state->delay_slot = (subopcode == 7);
				state->flow = indirect_jump;
				state->target = get_reg(31, regs, cregs);
			default:
				break;
			}
		default:
			break;
		}
		break;

	case op_LD_S:	/* LD_S c, [b, u7] */
		state->src1 = get_reg(FIELD_S_B(state->words[0]), regs, cregs);
		state->src2 = FIELD_S_u7(state->words[0]);
		state->dest = FIELD_S_C(state->words[0]);
		break;

	case op_LDB_S:
	case op_STB_S:
		/* no further handling required as byte accesses should not
		 * cause an unaligned access exception */
		state->zz = 1;
		break;

	case op_LDWX_S:	/* LDWX_S c, [b, u6] */
		state->x = 1;
		/* intentional fall-through */

	case op_LDW_S:	/* LDW_S c, [b, u6] */
		state->zz = 2;
		state->src1 = get_reg(FIELD_S_B(state->words[0]), regs, cregs);
		state->src2 = FIELD_S_u6(state->words[0]);
		state->dest = FIELD_S_C(state->words[0]);
		break;

	case op_ST_S:	/* ST_S c, [b, u7] */
		state->write = 1;
		state->src1 = get_reg(FIELD_S_C(state->words[0]), regs, cregs);
		state->src2 = get_reg(FIELD_S_B(state->words[0]), regs, cregs);
		state->src3 = FIELD_S_u7(state->words[0]);
		break;

	case op_STW_S:	/* STW_S c,[b,u6] */
		state->write = 1;
		state->zz = 2;
		state->src1 = get_reg(FIELD_S_C(state->words[0]), regs, cregs);
		state->src2 = get_reg(FIELD_S_B(state->words[0]), regs, cregs);
		state->src3 = FIELD_S_u6(state->words[0]);
		break;

	case op_SP:	/* LD_S|LDB_S b,[sp,u7], ST_S|STB_S b,[sp,u7] */
		/* note: we are ignoring possibility of:
		 * ADD_S, SUB_S, PUSH_S, POP_S as these should not
		 * cause unaliged exception anyway */
		state->write = BITS(state->words[0], 6, 6);
		state->zz = BITS(state->words[0], 5, 5);
		if (state->zz)
			break;	/* byte accesses should not come here */
		if (!state->write) {
			state->src1 = get_reg(28, regs, cregs);
			state->src2 = FIELD_S_u7(state->words[0]);
			state->dest = FIELD_S_B(state->words[0]);
		} else {
			state->src1 = get_reg(FIELD_S_B(state->words[0]), regs,
					cregs);
			state->src2 = get_reg(28, regs, cregs);
			state->src3 = FIELD_S_u7(state->words[0]);
		}
		break;

	case op_GP:	/* LD_S|LDB_S|LDW_S r0,[gp,s11/s9/s10] */
		/* note: ADD_S r0, gp, s11 is ignored */
		state->zz = BITS(state->words[0], 9, 10);
		state->src1 = get_reg(26, regs, cregs);
		state->src2 = state->zz ? FIELD_S_s10(state->words[0]) :
			FIELD_S_s11(state->words[0]);
		state->dest = 0;
		break;

	case op_Pcl:	/* LD_S b,[pcl,u10] */
		state->src1 = regs->ret & ~3;
		state->src2 = FIELD_S_u10(state->words[0]);
		state->dest = FIELD_S_B(state->words[0]);
		break;

	case op_BR_S:
		state->target = FIELD_S_s8(state->words[0]) + (addr & ~0x03);
		state->flow = direct_jump;
		state->is_branch = 1;
		break;

	case op_B_S:
		fieldA = (BITS(state->words[0], 9, 10) == 3) ?
			FIELD_S_s7(state->words[0]) :
			FIELD_S_s10(state->words[0]);
		state->target = fieldA + (addr & ~0x03);
		state->flow = direct_jump;
		state->is_branch = 1;
		break;

	case op_BL_S:
		state->target = FIELD_S_s13(state->words[0]) + (addr & ~0x03);
		state->flow = direct_call;
		state->is_branch = 1;
		break;

	default:
		break;
	}

	if (bytes_not_copied <= (8 - state->instr_len))
		return;

fault:	state->fault = 1;
}

long __kprobes get_reg(int reg, struct pt_regs *regs,
		       struct callee_regs *cregs)
{
	long *p;

	if (reg <= 12) {
		p = &regs->r0;
		return p[-reg];
	}

	if (cregs && (reg <= 25)) {
		p = &cregs->r13;
		return p[13-reg];
	}

	if (reg == 26)
		return regs->r26;
	if (reg == 27)
		return regs->fp;
	if (reg == 28)
		return regs->sp;
	if (reg == 31)
		return regs->blink;

	return 0;
}

void __kprobes set_reg(int reg, long val, struct pt_regs *regs,
		struct callee_regs *cregs)
{
	long *p;

	switch (reg) {
	case 0 ... 12:
		p = &regs->r0;
		p[-reg] = val;
		break;
	case 13 ... 25:
		if (cregs) {
			p = &cregs->r13;
			p[13-reg] = val;
		}
		break;
	case 26:
		regs->r26 = val;
		break;
	case 27:
		regs->fp = val;
		break;
	case 28:
		regs->sp = val;
		break;
	case 31:
		regs->blink = val;
		break;
	default:
		break;
	}
}

/*
 * Disassembles the insn at @pc and sets @next_pc to next PC (which could be
 * @pc +2/4/6 (ARCompact ISA allows free intermixing of 16/32 bit insns).
 *
 * If @pc is a branch
 *	-@tgt_if_br is set to branch target.
 *	-If branch has delay slot, @next_pc updated with actual next PC.
 */
int __kprobes disasm_next_pc(unsigned long pc, struct pt_regs *regs,
			     struct callee_regs *cregs,
			     unsigned long *next_pc, unsigned long *tgt_if_br)
{
	struct disasm_state instr;

	memset(&instr, 0, sizeof(struct disasm_state));
	disasm_instr(pc, &instr, 0, regs, cregs);

	*next_pc = pc + instr.instr_len;

	/* Instruction with possible two targets branch, jump and loop */
	if (instr.is_branch)
		*tgt_if_br = instr.target;

	/* For the instructions with delay slots, the fall through is the
	 * instruction following the instruction in delay slot.
	 */
	 if (instr.delay_slot) {
		struct disasm_state instr_d;

		disasm_instr(*next_pc, &instr_d, 0, regs, cregs);

		*next_pc += instr_d.instr_len;
	 }

	 /* Zero Overhead Loop - end of the loop */
	if (!(regs->status32 & STATUS32_L) && (*next_pc == regs->lp_end)
		&& (regs->lp_count > 1)) {
		*next_pc = regs->lp_start;
	}

	return instr.is_branch;
}

#endif /* CONFIG_KGDB || CONFIG_ARC_EMUL_UNALIGNED || CONFIG_KPROBES */
