| /* | |
| * Copyright (c) 2004-2005 The Regents of The University of Michigan | |
| * All rights reserved. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions are | |
| * met: redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer; | |
| * redistributions in binary form must reproduce the above copyright | |
| * notice, this list of conditions and the following disclaimer in the | |
| * documentation and/or other materials provided with the distribution; | |
| * neither the name of the copyright holders nor the names of its | |
| * contributors may be used to endorse or promote products derived from | |
| * this software without specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| * | |
| * Authors: Nathan Binkert | |
| * Ali Saidi | |
| */ | |
| #include "kern/linux/printk.hh" | |
| #include <sys/types.h> | |
| #include <algorithm> | |
| #include "base/trace.hh" | |
| #include "cpu/thread_context.hh" | |
| #include "sim/arguments.hh" | |
| using namespace std; | |
| void | |
| Printk(stringstream &out, Arguments args) | |
| { | |
| char *p = (char *)args++; | |
| while (*p) { | |
| switch (*p) { | |
| case '%': { | |
| bool more = true; | |
| bool islong = false; | |
| bool leftjustify = false; | |
| bool format = false; | |
| bool zero = false; | |
| int width = 0; | |
| while (more && *++p) { | |
| switch (*p) { | |
| case 'l': | |
| case 'L': | |
| islong = true; | |
| break; | |
| case '-': | |
| leftjustify = true; | |
| break; | |
| case '#': | |
| format = true; | |
| break; | |
| case '0': | |
| if (width) | |
| width *= 10; | |
| else | |
| zero = true; | |
| break; | |
| default: | |
| if (*p >= '1' && *p <= '9') | |
| width = 10 * width + *p - '0'; | |
| else | |
| more = false; | |
| break; | |
| } | |
| } | |
| bool hexnum = false; | |
| bool octal = false; | |
| bool sign = false; | |
| switch (*p) { | |
| case 'X': | |
| case 'x': | |
| hexnum = true; | |
| break; | |
| case 'O': | |
| case 'o': | |
| octal = true; | |
| break; | |
| case 'D': | |
| case 'd': | |
| sign = true; | |
| break; | |
| case 'P': | |
| format = true; | |
| M5_FALLTHROUGH; | |
| case 'p': | |
| hexnum = true; | |
| break; | |
| } | |
| switch (*p) { | |
| case 'D': | |
| case 'd': | |
| case 'U': | |
| case 'u': | |
| case 'X': | |
| case 'x': | |
| case 'O': | |
| case 'o': | |
| case 'P': | |
| case 'p': { | |
| if (hexnum) | |
| out << hex; | |
| if (octal) | |
| out << oct; | |
| if (format) { | |
| if (!zero) | |
| out.setf(ios::showbase); | |
| else { | |
| if (hexnum) { | |
| out << "0x"; | |
| width -= 2; | |
| } else if (octal) { | |
| out << "0"; | |
| width -= 1; | |
| } | |
| } | |
| } | |
| if (zero) | |
| out.fill('0'); | |
| if (width > 0) | |
| out.width(width); | |
| if (leftjustify && !zero) | |
| out.setf(ios::left); | |
| if (sign) { | |
| if (islong) | |
| out << (int64_t)args; | |
| else | |
| out << (int32_t)args; | |
| } else { | |
| if (islong) | |
| out << (uint64_t)args; | |
| else | |
| out << (uint32_t)args; | |
| } | |
| if (zero) | |
| out.fill(' '); | |
| if (width > 0) | |
| out.width(0); | |
| out << dec; | |
| ++args; | |
| } | |
| break; | |
| case 's': { | |
| const char *s = (char *)args; | |
| if (!s) | |
| s = "<NULL>"; | |
| if (width > 0) | |
| out.width(width); | |
| if (leftjustify) | |
| out.setf(ios::left); | |
| out << s; | |
| ++args; | |
| } | |
| break; | |
| case 'C': | |
| case 'c': { | |
| uint64_t mask = (*p == 'C') ? 0xffL : 0x7fL; | |
| uint64_t num; | |
| int cwidth; | |
| if (islong) { | |
| num = (uint64_t)args; | |
| cwidth = sizeof(uint64_t); | |
| } else { | |
| num = (uint32_t)args; | |
| cwidth = sizeof(uint32_t); | |
| } | |
| while (cwidth-- > 0) { | |
| char c = (char)(num & mask); | |
| if (c) | |
| out << c; | |
| num >>= 8; | |
| } | |
| ++args; | |
| } | |
| break; | |
| case 'b': { | |
| uint64_t n = (uint64_t)args++; | |
| char *s = (char *)args++; | |
| out << s << ": " << n; | |
| } | |
| break; | |
| case 'n': | |
| case 'N': { | |
| args += 2; | |
| } | |
| break; | |
| case 'r': | |
| case 'R': { | |
| args += 2; | |
| } | |
| break; | |
| case '%': | |
| out << '%'; | |
| break; | |
| } | |
| ++p; | |
| } | |
| break; | |
| case '\n': | |
| out << endl; | |
| ++p; | |
| break; | |
| case '\r': | |
| ++p; | |
| if (*p != '\n') | |
| out << endl; | |
| break; | |
| default: { | |
| size_t len = strcspn(p, "%\n\r\0"); | |
| out.write(p, len); | |
| p += len; | |
| } | |
| } | |
| } | |
| } |