// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/* Copyright (C) 2016-2018 Netronome Systems, Inc. */

#include <linux/bitops.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/types.h>

#include "nfp_asm.h"

const struct cmd_tgt_act cmd_tgt_act[__CMD_TGT_MAP_SIZE] = {
	[CMD_TGT_WRITE8_SWAP] =		{ 0x02, 0x42 },
	[CMD_TGT_WRITE32_SWAP] =	{ 0x02, 0x5f },
	[CMD_TGT_READ8] =		{ 0x01, 0x43 },
	[CMD_TGT_READ32] =		{ 0x00, 0x5c },
	[CMD_TGT_READ32_LE] =		{ 0x01, 0x5c },
	[CMD_TGT_READ32_SWAP] =		{ 0x02, 0x5c },
	[CMD_TGT_READ_LE] =		{ 0x01, 0x40 },
	[CMD_TGT_READ_SWAP_LE] =	{ 0x03, 0x40 },
	[CMD_TGT_ADD] =			{ 0x00, 0x47 },
	[CMD_TGT_ADD_IMM] =		{ 0x02, 0x47 },
};

static bool unreg_is_imm(u16 reg)
{
	return (reg & UR_REG_IMM) == UR_REG_IMM;
}

u16 br_get_offset(u64 instr)
{
	u16 addr_lo, addr_hi;

	addr_lo = FIELD_GET(OP_BR_ADDR_LO, instr);
	addr_hi = FIELD_GET(OP_BR_ADDR_HI, instr);

	return (addr_hi * ((OP_BR_ADDR_LO >> __bf_shf(OP_BR_ADDR_LO)) + 1)) |
		addr_lo;
}

void br_set_offset(u64 *instr, u16 offset)
{
	u16 addr_lo, addr_hi;

	addr_lo = offset & (OP_BR_ADDR_LO >> __bf_shf(OP_BR_ADDR_LO));
	addr_hi = offset != addr_lo;
	*instr &= ~(OP_BR_ADDR_HI | OP_BR_ADDR_LO);
	*instr |= FIELD_PREP(OP_BR_ADDR_HI, addr_hi);
	*instr |= FIELD_PREP(OP_BR_ADDR_LO, addr_lo);
}

void br_add_offset(u64 *instr, u16 offset)
{
	u16 addr;

	addr = br_get_offset(*instr);
	br_set_offset(instr, addr + offset);
}

static bool immed_can_modify(u64 instr)
{
	if (FIELD_GET(OP_IMMED_INV, instr) ||
	    FIELD_GET(OP_IMMED_SHIFT, instr) ||
	    FIELD_GET(OP_IMMED_WIDTH, instr) != IMMED_WIDTH_ALL) {
		pr_err("Can't decode/encode immed!\n");
		return false;
	}
	return true;
}

u16 immed_get_value(u64 instr)
{
	u16 reg;

	if (!immed_can_modify(instr))
		return 0;

	reg = FIELD_GET(OP_IMMED_A_SRC, instr);
	if (!unreg_is_imm(reg))
		reg = FIELD_GET(OP_IMMED_B_SRC, instr);

	return (reg & 0xff) | FIELD_GET(OP_IMMED_IMM, instr) << 8;
}

void immed_set_value(u64 *instr, u16 immed)
{
	if (!immed_can_modify(*instr))
		return;

	if (unreg_is_imm(FIELD_GET(OP_IMMED_A_SRC, *instr))) {
		*instr &= ~FIELD_PREP(OP_IMMED_A_SRC, 0xff);
		*instr |= FIELD_PREP(OP_IMMED_A_SRC, immed & 0xff);
	} else {
		*instr &= ~FIELD_PREP(OP_IMMED_B_SRC, 0xff);
		*instr |= FIELD_PREP(OP_IMMED_B_SRC, immed & 0xff);
	}

	*instr &= ~OP_IMMED_IMM;
	*instr |= FIELD_PREP(OP_IMMED_IMM, immed >> 8);
}

void immed_add_value(u64 *instr, u16 offset)
{
	u16 val;

	if (!immed_can_modify(*instr))
		return;

	val = immed_get_value(*instr);
	immed_set_value(instr, val + offset);
}

static u16 nfp_swreg_to_unreg(swreg reg, bool is_dst)
{
	bool lm_id, lm_dec = false;
	u16 val = swreg_value(reg);

	switch (swreg_type(reg)) {
	case NN_REG_GPR_A:
	case NN_REG_GPR_B:
	case NN_REG_GPR_BOTH:
		return val;
	case NN_REG_NNR:
		return UR_REG_NN | val;
	case NN_REG_XFER:
		return UR_REG_XFR | val;
	case NN_REG_LMEM:
		lm_id = swreg_lm_idx(reg);

		switch (swreg_lm_mode(reg)) {
		case NN_LM_MOD_NONE:
			if (val & ~UR_REG_LM_IDX_MAX) {
				pr_err("LM offset too large\n");
				return 0;
			}
			return UR_REG_LM | FIELD_PREP(UR_REG_LM_IDX, lm_id) |
				val;
		case NN_LM_MOD_DEC:
			lm_dec = true;
			fallthrough;
		case NN_LM_MOD_INC:
			if (val) {
				pr_err("LM offset in inc/dev mode\n");
				return 0;
			}
			return UR_REG_LM | UR_REG_LM_POST_MOD |
				FIELD_PREP(UR_REG_LM_IDX, lm_id) |
				FIELD_PREP(UR_REG_LM_POST_MOD_DEC, lm_dec);
		default:
			pr_err("bad LM mode for unrestricted operands %d\n",
			       swreg_lm_mode(reg));
			return 0;
		}
	case NN_REG_IMM:
		if (val & ~0xff) {
			pr_err("immediate too large\n");
			return 0;
		}
		return UR_REG_IMM_encode(val);
	case NN_REG_NONE:
		return is_dst ? UR_REG_NO_DST : REG_NONE;
	}

	pr_err("unrecognized reg encoding %08x\n", reg);
	return 0;
}

int swreg_to_unrestricted(swreg dst, swreg lreg, swreg rreg,
			  struct nfp_insn_ur_regs *reg)
{
	memset(reg, 0, sizeof(*reg));

	/* Decode destination */
	if (swreg_type(dst) == NN_REG_IMM)
		return -EFAULT;

	if (swreg_type(dst) == NN_REG_GPR_B)
		reg->dst_ab = ALU_DST_B;
	if (swreg_type(dst) == NN_REG_GPR_BOTH)
		reg->wr_both = true;
	reg->dst = nfp_swreg_to_unreg(dst, true);

	/* Decode source operands */
	if (swreg_type(lreg) == swreg_type(rreg) &&
	    swreg_type(lreg) != NN_REG_NONE)
		return -EFAULT;

	if (swreg_type(lreg) == NN_REG_GPR_B ||
	    swreg_type(rreg) == NN_REG_GPR_A) {
		reg->areg = nfp_swreg_to_unreg(rreg, false);
		reg->breg = nfp_swreg_to_unreg(lreg, false);
		reg->swap = true;
	} else {
		reg->areg = nfp_swreg_to_unreg(lreg, false);
		reg->breg = nfp_swreg_to_unreg(rreg, false);
	}

	reg->dst_lmextn = swreg_lmextn(dst);
	reg->src_lmextn = swreg_lmextn(lreg) | swreg_lmextn(rreg);

	return 0;
}

static u16 nfp_swreg_to_rereg(swreg reg, bool is_dst, bool has_imm8, bool *i8)
{
	u16 val = swreg_value(reg);
	bool lm_id;

	switch (swreg_type(reg)) {
	case NN_REG_GPR_A:
	case NN_REG_GPR_B:
	case NN_REG_GPR_BOTH:
		return val;
	case NN_REG_XFER:
		return RE_REG_XFR | val;
	case NN_REG_LMEM:
		lm_id = swreg_lm_idx(reg);

		if (swreg_lm_mode(reg) != NN_LM_MOD_NONE) {
			pr_err("bad LM mode for restricted operands %d\n",
			       swreg_lm_mode(reg));
			return 0;
		}

		if (val & ~RE_REG_LM_IDX_MAX) {
			pr_err("LM offset too large\n");
			return 0;
		}

		return RE_REG_LM | FIELD_PREP(RE_REG_LM_IDX, lm_id) | val;
	case NN_REG_IMM:
		if (val & ~(0x7f | has_imm8 << 7)) {
			pr_err("immediate too large\n");
			return 0;
		}
		*i8 = val & 0x80;
		return RE_REG_IMM_encode(val & 0x7f);
	case NN_REG_NONE:
		return is_dst ? RE_REG_NO_DST : REG_NONE;
	case NN_REG_NNR:
		pr_err("NNRs used with restricted encoding\n");
		return 0;
	}

	pr_err("unrecognized reg encoding\n");
	return 0;
}

int swreg_to_restricted(swreg dst, swreg lreg, swreg rreg,
			struct nfp_insn_re_regs *reg, bool has_imm8)
{
	memset(reg, 0, sizeof(*reg));

	/* Decode destination */
	if (swreg_type(dst) == NN_REG_IMM)
		return -EFAULT;

	if (swreg_type(dst) == NN_REG_GPR_B)
		reg->dst_ab = ALU_DST_B;
	if (swreg_type(dst) == NN_REG_GPR_BOTH)
		reg->wr_both = true;
	reg->dst = nfp_swreg_to_rereg(dst, true, false, NULL);

	/* Decode source operands */
	if (swreg_type(lreg) == swreg_type(rreg) &&
	    swreg_type(lreg) != NN_REG_NONE)
		return -EFAULT;

	if (swreg_type(lreg) == NN_REG_GPR_B ||
	    swreg_type(rreg) == NN_REG_GPR_A) {
		reg->areg = nfp_swreg_to_rereg(rreg, false, has_imm8, &reg->i8);
		reg->breg = nfp_swreg_to_rereg(lreg, false, has_imm8, &reg->i8);
		reg->swap = true;
	} else {
		reg->areg = nfp_swreg_to_rereg(lreg, false, has_imm8, &reg->i8);
		reg->breg = nfp_swreg_to_rereg(rreg, false, has_imm8, &reg->i8);
	}

	reg->dst_lmextn = swreg_lmextn(dst);
	reg->src_lmextn = swreg_lmextn(lreg) | swreg_lmextn(rreg);

	return 0;
}

#define NFP_USTORE_ECC_POLY_WORDS		7
#define NFP_USTORE_OP_BITS			45

static const u64 nfp_ustore_ecc_polynomials[NFP_USTORE_ECC_POLY_WORDS] = {
	0x0ff800007fffULL,
	0x11f801ff801fULL,
	0x1e387e0781e1ULL,
	0x17cb8e388e22ULL,
	0x1af5b2c93244ULL,
	0x1f56d5525488ULL,
	0x0daf69a46910ULL,
};

static bool parity(u64 value)
{
	return hweight64(value) & 1;
}

int nfp_ustore_check_valid_no_ecc(u64 insn)
{
	if (insn & ~GENMASK_ULL(NFP_USTORE_OP_BITS, 0))
		return -EINVAL;

	return 0;
}

u64 nfp_ustore_calc_ecc_insn(u64 insn)
{
	u8 ecc = 0;
	int i;

	for (i = 0; i < NFP_USTORE_ECC_POLY_WORDS; i++)
		ecc |= parity(nfp_ustore_ecc_polynomials[i] & insn) << i;

	return insn | (u64)ecc << NFP_USTORE_OP_BITS;
}
