#include <stdarg.h>
#include <reg.h>
#include <kernel/thread.h>
#include <platform/armemu/memmap.h>
#include <platform/debug.h>
#include <lib/printf.h>

int dputs(const char *str)
{
	enter_critical_section();

	while(*str != 0) {
		if(*str == '\n')
			*REG8(DEBUG_STDOUT) = '\r';
		*REG8(DEBUG_STDOUT) = *str++;
	}

	exit_critical_section();

	return 0;
}

int dprintf(const char *fmt, ...)
{
	char buf[256];
	int err;

	va_list ap;
	va_start(ap, fmt);
	err = vsprintf(buf, fmt, ap);
	va_end(ap);

	dputs(buf);

	return err;
}

int dvprintf(const char *fmt, va_list ap)
{
	char buf[256];
	int err;

	err = vsprintf(buf, fmt, ap);

	dputs(buf);

	return err;
}

void debug_dump_regs(void)
{
	*REG32(DEBUG_REGDUMP) = 1;
}

void debug_halt(void)
{
	*REG32(DEBUG_HALT) = 1;
	for(;;);
}

void debug_dump_memory_bytes(void *mem, int len)
{
	*REG32(DEBUG_MEMDUMPADDR) = (unsigned int)mem;
	*REG32(DEBUG_MEMDUMPLEN) = len;
	*REG32(DEBUG_MEMDUMP_BYTE) = 1;
}

void debug_dump_memory_halfwords(void *mem, int len)
{
	len /= 2;

	*REG32(DEBUG_MEMDUMPADDR) = (unsigned int)mem;
	*REG32(DEBUG_MEMDUMPLEN) = len;
	*REG32(DEBUG_MEMDUMP_HALFWORD) = 1;
}

void debug_dump_memory_words(void *mem, int len)
{
	len /= 4;

	*REG32(DEBUG_MEMDUMPADDR) = (unsigned int)mem;
	*REG32(DEBUG_MEMDUMPLEN) = len;
	*REG32(DEBUG_MEMDUMP_WORD) = 1;
}

void debug_set_trace_level(int trace_type, int level)
{
	if(trace_type < 0 || trace_type >= 4)
		return;

	*REG32(DEBUG_SET_TRACELEVEL_CPU + trace_type * 4) = level;
}

uint32_t debug_cycle_count()
{
	return *REG32(DEBUG_CYCLE_COUNT);
}
