diff options
| author | Megan Wachs <megan@sifive.com> | 2016-11-30 10:55:18 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-11-30 10:55:18 -0800 |
| commit | ae5f878d6acadabaa671a7a30b87e16eb1d718a7 (patch) | |
| tree | 20749a4e80815136d2129486b25202427b9ea30b /software/dhrystone/dhry_printf.c | |
| parent | e12b0338d24597f12263322216fbe4e6c6b8e12a (diff) | |
Bump Everything to Match new Freedom Repo (#8)
* Bump tool versions
* Use version of OpenOCD which can load programs into flash
* Bump OpenOCD to Handle ISSI Flash Programming
* Update Header files
* add initial support for hifive1
* add dhrystone
* add clock helper functions
* add openocd cfg file
* Demo_GPIO checkpoint -- compiles and runs but no blinky LEDs
* Remove riscv-tests submodule
* Remove FPGA files, as they are no longer relevant to this Repository
* Add openocd_upload script
* Add Pinmux Mappings
Adding the pinmux mappings to the Platform Header
* Add IOF Mappings to platform header
* Re-order the IOF Mapping declarations
* Add more useful things to platform headers
* Get GPIO Demo working again (except interrupts aren't working)
* Update README with more OS packages needed
A bare ubuntu-16.04.1-server installation could not run `make tools`
without these packages.
* bump openocd to get SCKDIV fix
* Remove duplicated help text for run_debug target
* Add package to README that is needed for openocd build
Without this package I was seeing two different failures like below
when running `make tools`.
/home/scottj/freedom-e-sdk/openocd/configure: line 4533: syntax error near unexpected token `0.23'
/home/scottj/freedom-e-sdk/openocd/configure: line 4533: `PKG_PROG_PKG_CONFIG(0.23)'
Makefile:70: recipe for target '/home/scottj/freedom-e-sdk/toolchain/bin/openocd' failed
make: *** [/home/scottj/freedom-e-sdk/toolchain/bin/openocd] Error 2
... or ...
+ autoconf
configure.ac:12: error: possibly undefined macro: AC_MSG_WARN
If this token and others are legitimate, please use m4_pattern_allow.
See the Autoconf documentation.
configure.ac:240: error: possibly undefined macro: AC_MSG_NOTICE
configure.ac:342: error: possibly undefined macro: AC_DEFINE
Makefile:70: recipe for target '/home/scottj/freedom-e-sdk/toolchain/bin/openocd' failed
make: *** [/home/scottj/freedom-e-sdk/toolchain/bin/openocd] Error 1
* Bump OpenOCD to not overwrite SCKDIV when flashing
* Roll back CoreMark
Diffstat (limited to 'software/dhrystone/dhry_printf.c')
| -rw-r--r-- | software/dhrystone/dhry_printf.c | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/software/dhrystone/dhry_printf.c b/software/dhrystone/dhry_printf.c new file mode 100644 index 0000000..1fdaac4 --- /dev/null +++ b/software/dhrystone/dhry_printf.c @@ -0,0 +1,271 @@ +/* The functions in this file are only meant to support Dhrystone on an + * embedded RV32 system and are obviously incorrect in general. */ + +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#undef putchar +int putchar(int ch) +{ + return write(1, &ch, 1) == 1 ? ch : -1; +} + +static void sprintf_putch(int ch, void** data) +{ + char** pstr = (char**)data; + **pstr = ch; + (*pstr)++; +} + +static unsigned long getuint(va_list *ap, int lflag) +{ + if (lflag) + return va_arg(*ap, unsigned long); + else + return va_arg(*ap, unsigned int); +} + +static long getint(va_list *ap, int lflag) +{ + if (lflag) + return va_arg(*ap, long); + else + return va_arg(*ap, int); +} + +static inline void printnum(void (*putch)(int, void**), void **putdat, + unsigned long num, unsigned base, int width, int padc) +{ + unsigned digs[sizeof(num)*8]; + int pos = 0; + + while (1) + { + digs[pos++] = num % base; + if (num < base) + break; + num /= base; + } + + while (width-- > pos) + putch(padc, putdat); + + while (pos-- > 0) + putch(digs[pos] + (digs[pos] >= 10 ? 'a' - 10 : '0'), putdat); +} + +static inline void print_double(void (*putch)(int, void**), void **putdat, + double num, int width, int prec) +{ + union { + double d; + uint64_t u; + } u; + u.d = num; + + if (u.u & (1ULL << 63)) { + putch('-', putdat); + u.u &= ~(1ULL << 63); + } + + for (int i = 0; i < prec; i++) + u.d *= 10; + + char buf[32], *pbuf = buf; + printnum(sprintf_putch, (void**)&pbuf, (unsigned long)u.d, 10, 0, 0); + if (prec > 0) { + for (int i = 0; i < prec; i++) { + pbuf[-i] = pbuf[-i-1]; + } + pbuf[-prec] = '.'; + pbuf++; + } + + for (char* p = buf; p < pbuf; p++) + putch(*p, putdat); +} + +static void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_list ap) +{ + register const char* p; + const char* last_fmt; + register int ch, err; + unsigned long num; + int base, lflag, width, precision, altflag; + char padc; + + while (1) { + while ((ch = *(unsigned char *) fmt) != '%') { + if (ch == '\0') + return; + fmt++; + putch(ch, putdat); + } + fmt++; + + // Process a %-escape sequence + last_fmt = fmt; + padc = ' '; + width = -1; + precision = -1; + lflag = 0; + altflag = 0; + reswitch: + switch (ch = *(unsigned char *) fmt++) { + + // flag to pad on the right + case '-': + padc = '-'; + goto reswitch; + + // flag to pad with 0's instead of spaces + case '0': + padc = '0'; + goto reswitch; + + // width field + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + for (precision = 0; ; ++fmt) { + precision = precision * 10 + ch - '0'; + ch = *fmt; + if (ch < '0' || ch > '9') + break; + } + goto process_precision; + + case '*': + precision = va_arg(ap, int); + goto process_precision; + + case '.': + if (width < 0) + width = 0; + goto reswitch; + + case '#': + altflag = 1; + goto reswitch; + + process_precision: + if (width < 0) + width = precision, precision = -1; + goto reswitch; + + // long flag + case 'l': + if (lflag) + goto bad; + goto reswitch; + + // character + case 'c': + putch(va_arg(ap, int), putdat); + break; + + // double + case 'f': + print_double(putch, putdat, va_arg(ap, double), width, precision); + break; + + // string + case 's': + if ((p = va_arg(ap, char *)) == NULL) + p = "(null)"; + if (width > 0 && padc != '-') + for (width -= strnlen(p, precision); width > 0; width--) + putch(padc, putdat); + for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) { + putch(ch, putdat); + p++; + } + for (; width > 0; width--) + putch(' ', putdat); + break; + + // (signed) decimal + case 'd': + num = getint(&ap, lflag); + if ((long) num < 0) { + putch('-', putdat); + num = -(long) num; + } + base = 10; + goto signed_number; + + // unsigned decimal + case 'u': + base = 10; + goto unsigned_number; + + // (unsigned) octal + case 'o': + // should do something with padding so it's always 3 octits + base = 8; + goto unsigned_number; + + // pointer + case 'p': + lflag = 1; + putch('0', putdat); + putch('x', putdat); + /* fall through to 'x' */ + + // (unsigned) hexadecimal + case 'x': + base = 16; + unsigned_number: + num = getuint(&ap, lflag); + signed_number: + printnum(putch, putdat, num, base, width, padc); + break; + + // escaped '%' character + case '%': + putch(ch, putdat); + break; + + // unrecognized escape sequence - just print it literally + default: + bad: + putch('%', putdat); + fmt = last_fmt; + break; + } + } +} + +int printf(const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + vprintfmt((void*)putchar, 0, fmt, ap); + + va_end(ap); + return 0; // incorrect return value, but who cares, anyway? +} + +int sprintf(char* str, const char* fmt, ...) +{ + va_list ap; + char* str0 = str; + va_start(ap, fmt); + + vprintfmt(sprintf_putch, (void**)&str, fmt, ap); + *str = 0; + + va_end(ap); + return str - str0; +} |
