mirror of
https://github.com/NotImplementedLife/FSPDS.git
synced 2025-06-19 01:15:34 -04:00
212 lines
3.8 KiB
C
212 lines
3.8 KiB
C
#include "log.h"
|
|
#include <stdarg.h>
|
|
|
|
// gcc translates inline asm "mov r7,r7" to "add r7, r7, #0"
|
|
// so we have to hardcode the intended instruction
|
|
#define MOV_R7_R7 ".BYTE 0x3f, 0x46"
|
|
|
|
#define MOV_R6_R6 ".BYTE 0x36, 0x46"
|
|
|
|
#define MOV_R5_R5 ".BYTE 0x2D, 0x46"
|
|
|
|
#define LOG_CODE(MOV_X_X, message) asm volatile \
|
|
( \
|
|
"push {r6} \r\n" \
|
|
"mov r6, %0 \r\n" \
|
|
MOV_X_X "\r\n" \
|
|
"pop {r6}\r\n" \
|
|
:: "r"(message) \
|
|
);
|
|
|
|
#define LOG_BUF 8
|
|
#define LOG_MSG 7
|
|
#define LOG_WRN 6
|
|
#define LOG_ERR 5
|
|
|
|
char* copy_str(char* dest, const char* src)
|
|
{
|
|
for(;*src;)
|
|
*(dest++) = *(src++);
|
|
*dest = '\0';
|
|
return dest;
|
|
}
|
|
|
|
__attribute__((target("thumb")))
|
|
void _log(int role, const char* message)
|
|
{
|
|
switch(role)
|
|
{
|
|
case LOG_MSG:
|
|
LOG_CODE(MOV_R7_R7, message); break;
|
|
case LOG_WRN:
|
|
LOG_CODE(MOV_R6_R6, message); break;
|
|
case LOG_ERR:
|
|
LOG_CODE(MOV_R5_R5, message); break;
|
|
case LOG_BUF:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static const char* hex_lower = "0123456789abcdef";
|
|
static const char* hex_upper = "0123456789ABCDEF";
|
|
|
|
char result[128];
|
|
|
|
__attribute__((target("thumb")))
|
|
void _logv(int role, char* dest, const char* message, va_list args)
|
|
{
|
|
char* built = result;
|
|
|
|
for(const char* msg=message; *msg;)
|
|
{
|
|
if(*msg=='%')
|
|
{
|
|
++msg;
|
|
if(*msg==0) break;
|
|
|
|
switch(*msg)
|
|
{
|
|
case 'i':
|
|
{
|
|
int val = va_arg(args, int);
|
|
|
|
if(val==0)
|
|
{
|
|
*(built++)='0';
|
|
++msg;
|
|
break;
|
|
}
|
|
|
|
if(val<0)
|
|
*(built++)='-', val = -val;
|
|
|
|
int nzeros = 0;
|
|
for(;val%10==0;val/=10) nzeros++;
|
|
|
|
int temp = 0;
|
|
for(;val;val/=10) temp=temp*10 + val%10;
|
|
for(;temp;temp/=10) *(built++)='0'+temp%10;
|
|
|
|
for(;nzeros--;) *(built++)='0';
|
|
|
|
++msg;
|
|
break;
|
|
}
|
|
case 'u':
|
|
{
|
|
unsigned int val = va_arg(args, unsigned int);
|
|
|
|
if(val==0)
|
|
{
|
|
*(built++)='0';
|
|
++msg;
|
|
break;
|
|
}
|
|
|
|
int nzeros = 0;
|
|
for(;val%10==0;val/=10) nzeros++;
|
|
|
|
int temp = 0;
|
|
for(;val;val/=10) temp=temp*10 + val%10;
|
|
for(;temp;temp/=10) *(built++)='0'+temp%10;
|
|
|
|
for(;nzeros--;) *(built++)='0';
|
|
|
|
++msg;
|
|
break;
|
|
}
|
|
case 's':
|
|
{
|
|
char* val = va_arg(args, char*);
|
|
|
|
while(*val) *(built++)=*(val++);
|
|
|
|
++msg;
|
|
break;
|
|
}
|
|
case 'b':
|
|
{
|
|
int val = va_arg(args, int);
|
|
if(val)
|
|
built = copy_str(built, "T");
|
|
else
|
|
built = copy_str(built, "F");
|
|
|
|
++msg;
|
|
break;
|
|
}
|
|
case 'B':
|
|
{
|
|
int val = va_arg(args, int);
|
|
if(val)
|
|
built = copy_str(built, "True");
|
|
else
|
|
built = copy_str(built, "False");
|
|
|
|
++msg;
|
|
break;
|
|
}
|
|
case 'x':
|
|
{
|
|
unsigned val = va_arg(args, unsigned);
|
|
int num_start = 0;
|
|
for(int i=0;i<8;i++)
|
|
{
|
|
int digit = (val & 0xF0000000)>>28;
|
|
val<<=4;
|
|
if(!num_start && digit==0)
|
|
continue;
|
|
num_start = 1;
|
|
*(built++) = hex_lower[digit];
|
|
}
|
|
if(!num_start)
|
|
{
|
|
*(built++)='0';
|
|
}
|
|
++msg;
|
|
break;
|
|
}
|
|
case 'X':
|
|
{
|
|
unsigned val = va_arg(args, unsigned);
|
|
int num_start = 0;
|
|
for(int i=0;i<8;i++)
|
|
{
|
|
int digit = (val & 0xF0000000)>>28;
|
|
val<<=4;
|
|
if(!num_start && digit==0)
|
|
continue;
|
|
num_start = 1;
|
|
*(built++) = hex_upper[digit];
|
|
}
|
|
if(!num_start)
|
|
{
|
|
*(built++)='0';
|
|
}
|
|
++msg;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*(built++)=*(msg++);
|
|
}
|
|
}
|
|
*(built)='\0';
|
|
|
|
_log(role, result);
|
|
if(role==LOG_BUF)
|
|
{
|
|
copy_str(dest, result);
|
|
}
|
|
}
|
|
|
|
|
|
void debug_log(const char* message, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, message);
|
|
_logv(LOG_MSG, 0, message, args);
|
|
va_end(args);
|
|
} |