#pragma once #include #include #include #include #define SYS_write 1 #define SYS_exit_group 231 #define STDOUT_FILENO 1 static void write(uint64_t fileno, void *buffer, size_t len) { uint64_t a,d; asm volatile("syscall" :"=a"(a),"=d"(d) :"a"(SYS_write),"D"(fileno),"S"(buffer),"d"(len) :"cc","memory","%rcx","%r11"); } [[noreturn]] static void exit_group(uint64_t code) { asm volatile( "syscall\n" "ud2" ::"a"(SYS_exit_group),"D"(code)); for (;;); } #define MAX(x, y) (((x) > (y)) ? (x) : (y)) #define MIN(x, y) (((x) < (y)) ? (x) : (y)) #define xstr(s) str(s) #define str(s) #s typedef uint64_t bcdint; typedef uint64_t num; static void printns(size_t len, unsigned char chars[len]) { write(STDOUT_FILENO, chars, len); } static void printptr(uintptr_t v) { char buf[sizeof(uintptr_t)*2] = { }; char *p = buf+countof(buf); for (size_t i = 0; i < countof(buf); i++) { p--; if ((v & 0x0F) < 0xA) { *p = '0' + (v & 0x0F); } else { *p = 'A' - 0xA + (v & 0x0F); } v >>= 4; } write(STDOUT_FILENO, p, countof(buf)); } static void print_many_char(size_t len, char chars[len]) { write(STDOUT_FILENO, chars, len); } #define print(string) print_many_char(sizeof(string)-1, string) static void printd(unsigned long v) { if (!v) { print("0"); return; } char buf[32]; char *p = buf+32; unsigned count = 0; while (v) { p--; *p = '0' + (v % 10); v /= 10; count++; } write(STDOUT_FILENO, p, count); } static void snprintd(unsigned long v, size_t n, unsigned char d[n]) { memset(d, 0, n); if (!v) { d[n-1] = '0'; return; } unsigned char *p = d+n; unsigned count = 0; while (v) { p--; *p = '0' + (v % 10); v /= 10; if (p == d) return; } } static void printh(unsigned long v) { if (!v) { print("0"); return; } char buf[32]; char *p = buf+32; unsigned count = 0; while (v) { p--; if ((v & 0x0F) < 0xA) { *p = '0' + (v & 0x0F); } else { *p = 'A' - 0xA + (v & 0x0F); } v >>= 4; count++; } write(STDOUT_FILENO, p, count); } static void snprinth(unsigned long v, size_t n, unsigned char d[n]) { memset(d, 0, n); if (!v) { d[n-1] = '0'; return; } unsigned char *p = d+n; unsigned count = 0; while (v) { p--; if ((v & 0x0F) < 0xA) { *p = '0' + (v & 0x0F); } else { *p = 'A' - 0xA + (v & 0x0F); } v >>= 4; if (p == d) return; } } static void print_hex_char(unsigned char v) { char buf[2]; if ((v >> 4) < 0x0A) { buf[0] = '0' + (v >> 4); } else { buf[0] = 'A' - 0xA + (v >> 4); } if ((v & 0x0F) < 0xA) { buf[1] = '0' + (v & 0x0F); } else { buf[1] = 'A' - 0xA + (v & 0x0F); } write(STDOUT_FILENO, buf, sizeof(buf)); } static void print_pre_hex(size_t len, unsigned char prefix[len], unsigned long v) { printns(len, prefix); printh(v); } static void print_pre_ptr(size_t len, unsigned char prefix[len], void *ptr) { printns(len, prefix); printptr((uintptr_t)ptr); } #define print_watch_ptr(expr) print_pre_ptr(\ sizeof(#expr ": ")-1, (unsigned char*)(#expr ": "), expr) #define print_watch_hex(expr) print_pre_hex(\ sizeof(#expr ": ")-1, (unsigned char*)(#expr ": "), expr) static bcdint grabbcd(unsigned char *s, unsigned char **end) { bcdint r = 0; for (; *s >= '0' && *s <= '9'; s++) r = (r << 4) + (*s - '0'); if (end) *end = s; return r; } static unsigned long grabnum(unsigned char *s, unsigned char **end) { unsigned long r = 0; for (; *s >= '0' && *s <= '9'; s++) r = r * 10 + (*s - '0'); if (end) *end = s; return r; } // from wikipedia, the free encyclopedia // https://en.wikipedia.org/wiki/Binary-coded_decimal static bcdint bcdadd(bcdint a, bcdint b) { bcdint t1, t2; t1 = a + 0x0666666666666666; t2 = t1 ^ b; t1 = t1 + b; t2 = t1 ^ t2; t2 = ~t2 & 0x1111111111111110; t2 = (t2 >> 2) | (t2 >> 3); return t1 - t2; } // https://homepage.cs.uiowa.edu/~jones/bcd/bcd.html static bcdint bcdcomp(bcdint a) { bcdint t1, t2, t3, t4, t5, t6; t1 = 0xFFFFFFFFFFFFFFFF - a; t2 = - a; t3 = t1 ^ 0x0000000000000001; t4 = t2 ^ t3; t5 = ~t4 & 0x1111111111111110; t6 = (t5 >> 2) | (t5 >> 3); return t2 - t6; } static bcdint bcdsub(bcdint a, bcdint b) { return bcdadd(a, bcdcomp(b)); } static num bcdtonum(bcdint a) { return 0 + ((a >> 0) & 0xF) * 1 + ((a >> 4) & 0xF) * 10 + ((a >> 8) & 0xF) * 100 + ((a >> 12) & 0xF) * 1000 + ((a >> 16) & 0xF) * 10000 + ((a >> 20) & 0xF) * 100000 + ((a >> 24) & 0xF) * 1000000 + ((a >> 28) & 0xF) * 10000000 + ((a >> 32) & 0xF) * 100000000 + ((a >> 36) & 0xF) * 1000000000 + ((a >> 40) & 0xF) * 10000000000 + ((a >> 44) & 0xF) * 100000000000 + ((a >> 48) & 0xF) * 1000000000000 + ((a >> 52) & 0xF) * 10000000000000 + ((a >> 56) & 0xF) * 100000000000000 + ((a >> 60) & 0xF) * 1000000000000000; } static bcdint numtobcd(num a) { bcdint r = 0; while (a) { r <<= 4; r |= (a % 10); a /= 10; } return r; }