From a113ec989b74acf6a8eac68bbe41aab141d0235c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 5 Mar 2019 11:40:31 +0000 Subject: [PATCH] tests/tcg: provide a minilib for system tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Cc: Kevin Wolf Signed-off-by: Alex Bennée --- tests/tcg/Makefile | 1 + tests/tcg/minilib/Makefile.target | 21 +++++ tests/tcg/minilib/minilib.h | 25 ++++++ tests/tcg/minilib/printf.c | 133 ++++++++++++++++++++++++++++++ 4 files changed, 180 insertions(+) create mode 100644 tests/tcg/minilib/Makefile.target create mode 100644 tests/tcg/minilib/minilib.h create mode 100644 tests/tcg/minilib/printf.c diff --git a/tests/tcg/Makefile b/tests/tcg/Makefile index 8dfd1a76b9..1cdd628e96 100644 --- a/tests/tcg/Makefile +++ b/tests/tcg/Makefile @@ -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 diff --git a/tests/tcg/minilib/Makefile.target b/tests/tcg/minilib/Makefile.target new file mode 100644 index 0000000000..3ed8077d0f --- /dev/null +++ b/tests/tcg/minilib/Makefile.target @@ -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 $@ diff --git a/tests/tcg/minilib/minilib.h b/tests/tcg/minilib/minilib.h new file mode 100644 index 0000000000..e23361380a --- /dev/null +++ b/tests/tcg/minilib/minilib.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2015 Virtual Open Systems SAS + * Author: Alexander Spyridakis + * + * 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_ */ diff --git a/tests/tcg/minilib/printf.c b/tests/tcg/minilib/printf.c new file mode 100644 index 0000000000..121620cb16 --- /dev/null +++ b/tests/tcg/minilib/printf.c @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2015 Virtual Open Systems SAS + * Author: Alexander Spyridakis + * + * printf based on implementation by Kevin Wolf + * + * 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); +}