tests/tcg: provide a minilib for system tests
We will likely want a few common functions to make up for the fact we don't have a libc and we don't want to feel like we are programming by banging rocks together. I've purloined the printf function from: https://git.virtualopensystems.com/dev/tcg_baremetal_tests Although I have tweaked the names to avoid confusing GCC about clashing with builtins. Cc: Alexander Spyridakis <a.spyridakis@virtualopensystems.com> Cc: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
This commit is contained in:
parent
d72132c02e
commit
a113ec989b
@ -95,6 +95,7 @@ else
|
||||
# For softmmu targets we include a different Makefile fragement as the
|
||||
# build options for bare programs are usually pretty different. They
|
||||
# are expected to provide their own build recipes.
|
||||
-include $(SRC_PATH)/tests/tcg/minilib/Makefile.target
|
||||
-include $(SRC_PATH)/tests/tcg/$(TARGET_BASE_ARCH)/Makefile.softmmu-target
|
||||
ifneq ($(TARGET_BASE_ARCH),$(TARGET_NAME))
|
||||
-include $(SRC_PATH)/tests/tcg/$(TARGET_NAME)/Makefile.softmmu-target
|
||||
|
21
tests/tcg/minilib/Makefile.target
Normal file
21
tests/tcg/minilib/Makefile.target
Normal file
@ -0,0 +1,21 @@
|
||||
#
|
||||
# System test minilib objects
|
||||
#
|
||||
# The system tests are very constrained in terms of the library they
|
||||
# support but we are not savages. We provide a few helpful routines
|
||||
# that can be shared with the tests for basic I/O.
|
||||
#
|
||||
# They assume each arch has provided a putc function.
|
||||
#
|
||||
|
||||
SYSTEM_MINILIB_SRC=$(SRC_PATH)/tests/tcg/minilib
|
||||
MINILIB_SRCS=$(wildcard $(SYSTEM_MINILIB_SRC)/*.c)
|
||||
MINILIB_OBJS=$(patsubst $(SYSTEM_MINILIB_SRC)/%.c, %.o, $(MINILIB_SRCS))
|
||||
|
||||
MINILIB_CFLAGS+=-nostdlib -ggdb -O0
|
||||
MINILIB_INC=-isystem $(SYSTEM_MINILIB_SRC)
|
||||
|
||||
.PRECIOUS: $(MINILIB_OBJS)
|
||||
|
||||
%.o: $(SYSTEM_MINILIB_SRC)/%.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
25
tests/tcg/minilib/minilib.h
Normal file
25
tests/tcg/minilib/minilib.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Virtual Open Systems SAS
|
||||
* Author: Alexander Spyridakis <a.spyridakis@virtualopensystems.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.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only
|
||||
*/
|
||||
|
||||
#ifndef _MINILIB_H_
|
||||
#define _MINILIB_H_
|
||||
|
||||
/*
|
||||
* Provided by the individual arch
|
||||
*/
|
||||
extern void __sys_outc(char c);
|
||||
|
||||
/*
|
||||
* Provided by the common minilib
|
||||
*/
|
||||
void ml_printf(const char *fmt, ...);
|
||||
|
||||
#endif /* _MINILIB_H_ */
|
133
tests/tcg/minilib/printf.c
Normal file
133
tests/tcg/minilib/printf.c
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Virtual Open Systems SAS
|
||||
* Author: Alexander Spyridakis <a.spyridakis@virtualopensystems.com>
|
||||
*
|
||||
* printf based on implementation by Kevin Wolf <kwolf@redhat.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.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only
|
||||
*/
|
||||
|
||||
#include "minilib.h"
|
||||
|
||||
typedef __builtin_va_list va_list;
|
||||
#define va_start(ap, X) __builtin_va_start(ap, X)
|
||||
#define va_arg(ap, type) __builtin_va_arg(ap, type)
|
||||
#define va_end(ap) __builtin_va_end(ap)
|
||||
|
||||
static void print_str(char *s)
|
||||
{
|
||||
while (*s) {
|
||||
__sys_outc(*s++);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_num(unsigned long long value, int base)
|
||||
{
|
||||
char digits[] = "0123456789abcdef";
|
||||
char buf[32];
|
||||
int i = sizeof(buf) - 2, j;
|
||||
|
||||
/* Set the buffer to 0. See problem of before. */
|
||||
for (j = 0; j < 32; j++) {
|
||||
buf[j] = 0;
|
||||
}
|
||||
|
||||
do {
|
||||
buf[i--] = digits[value % base];
|
||||
value /= base;
|
||||
} while (value);
|
||||
|
||||
print_str(&buf[i + 1]);
|
||||
}
|
||||
|
||||
void ml_printf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *str;
|
||||
int base;
|
||||
int has_long;
|
||||
int alt_form;
|
||||
unsigned long long val;
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
for (; *fmt; fmt++) {
|
||||
if (*fmt != '%') {
|
||||
__sys_outc(*fmt);
|
||||
continue;
|
||||
}
|
||||
fmt++;
|
||||
|
||||
if (*fmt == '#') {
|
||||
fmt++;
|
||||
alt_form = 1;
|
||||
} else {
|
||||
alt_form = 0;
|
||||
}
|
||||
|
||||
if (*fmt == 'l') {
|
||||
fmt++;
|
||||
if (*fmt == 'l') {
|
||||
fmt++;
|
||||
has_long = 2;
|
||||
} else {
|
||||
has_long = 1;
|
||||
}
|
||||
} else {
|
||||
has_long = 0;
|
||||
}
|
||||
|
||||
switch (*fmt) {
|
||||
case 'x':
|
||||
case 'p':
|
||||
base = 16;
|
||||
goto convert_number;
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'u':
|
||||
base = 10;
|
||||
goto convert_number;
|
||||
case 'o':
|
||||
base = 8;
|
||||
goto convert_number;
|
||||
|
||||
convert_number:
|
||||
switch (has_long) {
|
||||
case 0:
|
||||
val = va_arg(ap, unsigned int);
|
||||
break;
|
||||
case 1:
|
||||
val = va_arg(ap, unsigned long);
|
||||
break;
|
||||
case 2:
|
||||
val = va_arg(ap, unsigned long long);
|
||||
break;
|
||||
}
|
||||
|
||||
if (alt_form && base == 16) {
|
||||
print_str("0x");
|
||||
}
|
||||
|
||||
print_num(val, base);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
str = va_arg(ap, char*);
|
||||
print_str(str);
|
||||
break;
|
||||
case '%':
|
||||
__sys_outc(*fmt);
|
||||
break;
|
||||
default:
|
||||
__sys_outc('%');
|
||||
__sys_outc(*fmt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
}
|
Loading…
Reference in New Issue
Block a user