/*
 * SerialICE
 *
 * Copyright (C) 2009 coresystems GmbH
 * Copyright (C) 2016 Patrick Rudolph <siro@das-labor.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#ifndef CONSOLE_SERIALICE_PRIV_H
#define CONSOLE_SERIALICE_PRIV_H

#include <stdint.h>

/* String functions */

#define sio_put_nibble(nibble)	\
	do { \
		if (nibble > 9)		\
			nibble += ('a' - 10);	\
			else			\
			nibble += '0';	\
			sio_putc(nibble);	\
	} while (0)

/* MSR functions */

typedef struct { u32 lo, hi; } msr_t;

static inline msr_t rdmsr(u32 index, u32 key)
{
	msr_t result;

	__asm__ __volatile__ (
		"rdmsr"
		: "=a" (result.lo), "=d" (result.hi)
		: "c" (index), "D" (key)
	);
	return result;
}

static inline void wrmsr(u32 index, msr_t msr, u32 key)
{
	__asm__ __volatile__ (
		"wrmsr"
		: /* No outputs */
		: "c" (index), "a" (msr.lo), "d" (msr.hi), "D" (key)
	);
}

/* CPUID functions */

static inline u32 s_cpuid_eax(u32 op, u32 op2)
{
	u32 eax;

	__asm__("cpuid"
			: "=a" (eax)
			: "a" (op), "c" (op2)
			: "ebx", "edx");
	return eax;
}

static inline u32 s_cpuid_ebx(u32 op, u32 op2)
{
	u32 ebx;

	__asm__("cpuid"
			: "=b" (ebx)
			: "a" (op), "c" (op2)
			: "edx");
	return ebx;
}

static inline u32 s_cpuid_ecx(u32 op, u32 op2)
{
	u32 ecx;

	__asm__("cpuid"
			: "=c" (ecx)
			: "a" (op), "c" (op2)
			: "ebx", "edx");
	return ecx;
}

static inline u32 s_cpuid_edx(u32 op, u32 op2)
{
	u32 edx;

	__asm__("cpuid"
			: "=d" (edx)
			: "a" (op), "c" (op2)
			: "ebx");
	return edx;
}

#endif
