/*
 * Tests vector instruction support
 *
 * Copyright 2018 IBM Corp.
 *
 * Authors:
 *    Janosch Frank <frankja@de.ibm.com>
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Library General Public License version 2.
 */
#include <libcflat.h>
#include <asm/page.h>
#include <asm/facility.h>
#include <asm/interrupt.h>
#include <asm-generic/barrier.h>

static uint8_t pagebuf[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));

/* Fills all vector registers with data from addr */
static inline void vlm_all(unsigned long *addr)
{
	asm volatile(" .machine z13\n"
		     " vlm 0, 15, %[a]\n"
		     : : [a]  "Q" (*addr)
		     :	"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8",
			"v9", "v10", "v11", "v12", "v13", "v14", "v15");
	asm volatile(" .machine z13\n"
		     " vlm 16, 31, %[a]\n"
		     : : [a]  "Q" (*(addr+256/8))
		     :	"v16", "v17", "v18", "v19", "v20", "v21", "v22",
			"v23", "v24", "v25", "v26", "v27", "v28", "v29",
			"v30", "v31");
}

static void test_add(void)
{
	static struct prm {
		__uint128_t a,b,c;
	} prm __attribute__((aligned(16)));

	prm.a = prm.b = prm.c = 21;

	asm volatile(" .machine z13\n"
		     " vl 0, %[v1]\n"
		     " vl 1, %[v2]\n"
		     " va 2, 0, 1, 4\n"
		     " vst 2, %[v3]\n"
		     : [v3]  "=Q" (prm.c)
		     : [v1]  "Q" (prm.a), [v2]  "Q" (prm.b)
		     : "v0", "v1", "v2", "memory");
	report(prm.c == 42, "adding 21");
}

/* z14 vector extension test */
static void test_ext1_nand(void)
{
	bool has_vext = test_facility(134);
	static struct prm {
		__uint128_t a,b,c;
	} prm __attribute__((aligned(16)));

	if (!has_vext) {
		report_skip("Vector extensions 1 is not available");
		return;
	}

	memset(&prm, 0xff, sizeof(prm));

	asm volatile(" .machine z13\n"
		     " vl 0, %[v1]\n"
		     " vl 1, %[v2]\n"
		     " .byte 0xe7, 0x20, 0x10, 0x00, 0x00, 0x6e\n" /* vnn */
		     " vst 2, %[v3]\n"
		     : [v3]  "=Q" (prm.c)
		     : [v1]  "Q" (prm.a), [v2]  "Q" (prm.b)
		     : "v0", "v1", "v2", "memory");
	report(!prm.c, "nand ff");
}

/* z14 bcd extension test */
static void test_bcd_add(void)
{
	bool has_bcd = test_facility(135);
	static struct prm {
		__uint128_t a,b,c;
	} prm __attribute__((aligned(16)));

	if (!has_bcd) {
		report_skip("Vector BCD extensions is not available");
		return;
	}

	prm.c = 0;
	prm.a = prm.b = 0b001000011100;

	asm volatile(" .machine z13\n"
		     " vl 0, %[v1]\n"
		     " vl 1, %[v2]\n"
		     " .byte 0xe6, 0x20, 0x10, 0x01, 0x00, 0x71\n" /* vap */
		     " vst 2, %[v3]\n"
		     : [v3]  "=Q" (prm.c)
		     : [v1]  "Q" (prm.a), [v2]  "Q" (prm.b)
		     : "v0", "v1", "v2", "memory");
	report(prm.c == 0x42c, "bcd add 21");
}

static void init(void)
{
	/* Enable vector instructions */
	ctl_set_bit(0, 17);

	/* Preset vector registers to 0xff */
	memset(pagebuf, 0xff, PAGE_SIZE);
	vlm_all((u64*)pagebuf);
}

int main(void)
{
	bool has_vregs = test_facility(129);

	report_prefix_push("vector");
	if (!has_vregs) {
		report_skip("Basic vector facility is not available");
		goto done;
	}

	init();
	test_add();
	test_ext1_nand();
	test_bcd_add();

done:
	report_prefix_pop();
	return report_summary();
}
