diff options
Diffstat (limited to 'clib/src/misc.c')
-rw-r--r-- | clib/src/misc.c | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/clib/src/misc.c b/clib/src/misc.c new file mode 100644 index 0000000..c79bd13 --- /dev/null +++ b/clib/src/misc.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) International Business Machines Corp., 2014 + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * File: misc.c + * Author: Shaun Wetzstein <shaun@us.ibm.com> + * Descr: + * Note: + * Date: 07/26/09 + */ + +#include <stdarg.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> + +#include "misc.h" + +inline void prefetch(void *addr, size_t len, ...) +{ + va_list v; + va_start(v, len); + int w = va_arg(v, int); + int l = va_arg(v, int); + va_end(v); + + while (0 < len) { + if (w) { + switch (l) { + case 0: + __builtin_prefetch(addr, 1, 0); + break; + case 1: + __builtin_prefetch(addr, 1, 1); + break; + case 2: + __builtin_prefetch(addr, 1, 2); + break; + } + } else { + switch (l) { + case 0: + __builtin_prefetch(addr, 0, 0); + break; + case 1: + __builtin_prefetch(addr, 0, 1); + break; + case 2: + __builtin_prefetch(addr, 0, 2); + break; + } + } + len -= sizeof addr; + } +} + +unsigned long align(unsigned long size, unsigned long offset) +{ + --offset; + return (size + offset) & ~offset; +} + +void print_binary(FILE * __out, void *__data, size_t __len) +{ + static const char *__ascii[] = { + "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", + "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111", + }; + + if (__data == NULL) + return; + if (__out == NULL) + __out = stdout; + + size_t i; + for (i = 0; i < __len; i++) { + unsigned char c = *(unsigned char *)(__data + i); + + fprintf(__out, "%4.4s%4.4s", + __ascii[(c & 0xF0) >> 4], __ascii[c & 0x0F]); + } +} + +#if 0 +void dump_memory(FILE * file, unsigned long addr, const void *buf, size_t size) +{ + if (size <= 0 || buf == NULL) + return; + if (file == NULL) + file = stdout; + + unsigned long *ul = (unsigned long *)buf; + char hex[64] = { 0, }, ascii[32] = { + 0,}, c; + int hl = 0, al = 0; + + int cnt = size / sizeof(unsigned long); + + int i; + for (i = 0; i < cnt; i++) { + hl += snprintf(hex + hl, sizeof hex, "%08lx", ul[i]); + + c = (ul[i] & 0xFF000000) >> 24; + al += + snprintf(ascii + al, sizeof ascii, "%c", + (isprint(c) ? c : '.')); + + c = (ul[i] & 0x00FF0000) >> 16; + al += + snprintf(ascii + al, sizeof ascii, "%c", + (isprint(c) ? c : '.')); + + c = (ul[i] & 0x0000FF00) >> 8; + al += + snprintf(ascii + al, sizeof ascii, "%c", + (isprint(c) ? c : '.')); + + c = (ul[i] & 0x000000FF) >> 0; + al += + snprintf(ascii + al, sizeof ascii, "%c", + (isprint(c) ? c : '.')); + + if ((i + 1) % 4 == 0) { + fprintf(file, " %08lx [%s] [%s]\n", addr, hex, ascii); + + addr += 4 * sizeof(unsigned long); + hl = al = 0; + + memset(hex, 0, sizeof hex); + memset(ascii, 0, sizeof ascii); + } else { + hl += snprintf(hex + hl, sizeof hex, " "); + } + } + + int j; + for (j = 0; j < (i % 4); j++) { + hl += snprintf(hex + hl, sizeof hex, "%08lx ", 0ul); + al += snprintf(ascii + al, sizeof ascii, "%4.4s", "...."); + } + + if (i % 4 != 0) { + fprintf(file, " %08lx [%s] [%s]\n", addr, hex, ascii); + } + + return; +} +#endif + +/* + * "aaaaaaaa [wwwwwwww xxxxxxxx yyyyyyyy zzzzzzzz] [........ ........]" + */ +void dump_memory(FILE * __out, uint32_t __addr, const void *__restrict __buf, + size_t __buf_sz) +{ + if (__buf_sz <= 0 || __buf == NULL) + return; + if (__out == NULL) + __out = stdout; + + size_t hex_size = 16 * 2; // 16 bytes per doubleword + size_t ascii_size = 8 * 2; // 8 bytes per doubleword + + uint8_t hex[hex_size + 1], ascii[hex_size + 1]; + memset(hex, '.', hex_size), memset(ascii, '.', ascii_size); + + void print_line(void) { + fprintf(__out, "%08x ", __addr); + + fprintf(__out, "[%.8s %.8s %.8s %.8s] ", + hex + 0, hex + 8, hex + 16, hex + 24); + + fprintf(__out, "[%.8s %.8s]\n", ascii + 0, ascii + 8); + } + + size_t s = __addr % 16, i = 0; + __addr &= ~0xF; + + for (i = s; i < __buf_sz + s; i++) { + unsigned char c = ((unsigned char *)__buf)[i - s]; + + hex[((i << 1) + 0) % hex_size] = "0123456789abcdef"[c >> 4]; + hex[((i << 1) + 1) % hex_size] = "0123456789abcdef"[c & 0xf]; + + ascii[i % ascii_size] = isprint(c) ? c : '.'; + + if (i == 0) + continue; + + if ((i + 1) % ascii_size == 0) { + print_line(); + memset(hex, '.', hex_size), memset(ascii, '.', + ascii_size); + + __addr += ascii_size; + } + } + + if (i % ascii_size) + print_line(); + + return; +} + +int __round_pow2(int size) +{ + size--; + + size |= size >> 1; + size |= size >> 2; + size |= size >> 4; + size |= size >> 8; + size |= size >> 16; + + return ++size; +} |