|
@@ -3,6 +3,62 @@
|
|
|
#include <types/size.h>
|
|
|
#include <types/stdint.h>
|
|
|
|
|
|
+#define __32bit_system
|
|
|
+
|
|
|
+#ifdef __32bit_system
|
|
|
+uint64_t do_div(uint64_t a, uint64_t b, uint64_t* remainder)
|
|
|
+{
|
|
|
+ uint64_t r = 0, q = 0;
|
|
|
+ int32_t i;
|
|
|
+ for (i = 0; i < 64; i++) {
|
|
|
+ r = (r << 1) + (a >> 63);
|
|
|
+ a <<= 1;
|
|
|
+ q <<= 1;
|
|
|
+ if (r >= b) {
|
|
|
+ r -= b;
|
|
|
+ q += 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (remainder)
|
|
|
+ *remainder = r;
|
|
|
+ return q;
|
|
|
+}
|
|
|
+
|
|
|
+int64_t do_div_s(int64_t a, int64_t b, uint64_t* remainder)
|
|
|
+{
|
|
|
+ int32_t qf = 0, rf = 0;
|
|
|
+ if (a < 0) {
|
|
|
+ qf = rf = 1;
|
|
|
+ a = -a;
|
|
|
+ }
|
|
|
+ if (b < 0) {
|
|
|
+ qf ^= 1;
|
|
|
+ b = -b;
|
|
|
+ }
|
|
|
+
|
|
|
+ int64_t quotient = do_div(a, b, (uint64_t*)remainder);
|
|
|
+
|
|
|
+ if (qf)
|
|
|
+ quotient = -quotient;
|
|
|
+ if (remainder && rf)
|
|
|
+ *remainder = -*remainder;
|
|
|
+
|
|
|
+ return quotient;
|
|
|
+}
|
|
|
+
|
|
|
+int64_t __divdi3(int64_t a, int64_t b)
|
|
|
+{
|
|
|
+ return do_div_s(a, b, (uint64_t*)0);
|
|
|
+}
|
|
|
+
|
|
|
+int64_t __moddi3(int64_t a, int64_t b)
|
|
|
+{
|
|
|
+ uint64_t remainder = 0;
|
|
|
+ do_div_s(a, b, &remainder);
|
|
|
+ return remainder;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
// where n is in the range of [0, 9]
|
|
|
static inline char d_to_c(int32_t n)
|
|
|
{
|
|
@@ -49,7 +105,7 @@ static inline char X_to_c(int32_t n)
|
|
|
}
|
|
|
|
|
|
ssize_t
|
|
|
-snprint_decimal(
|
|
|
+snprint_decimal32(
|
|
|
char* buf,
|
|
|
size_t buf_size,
|
|
|
int32_t num)
|
|
@@ -89,6 +145,47 @@ snprint_decimal(
|
|
|
return n_write;
|
|
|
}
|
|
|
|
|
|
+ssize_t
|
|
|
+snprint_decimal64(
|
|
|
+ char* buf,
|
|
|
+ size_t buf_size,
|
|
|
+ int64_t num)
|
|
|
+{
|
|
|
+ ssize_t n_write = 0;
|
|
|
+
|
|
|
+ if (num < 0) {
|
|
|
+ do_write_if_free(buf, buf_size, '-');
|
|
|
+ ++n_write;
|
|
|
+ num *= (-1);
|
|
|
+ }
|
|
|
+
|
|
|
+ char* orig_buf = buf;
|
|
|
+
|
|
|
+ do {
|
|
|
+ do_write_if_free(buf, buf_size, d_to_c(num % 10));
|
|
|
+ num /= 10;
|
|
|
+ ++n_write;
|
|
|
+ } while (num != 0);
|
|
|
+
|
|
|
+ // prepend trailing '\0'
|
|
|
+ if (buf_size > 0)
|
|
|
+ *buf = 0x00;
|
|
|
+
|
|
|
+ // move buf pointer to the last digit of number
|
|
|
+ --buf;
|
|
|
+
|
|
|
+ // reverse output
|
|
|
+ while (orig_buf < buf) {
|
|
|
+ char c = *buf;
|
|
|
+ *buf = *orig_buf;
|
|
|
+ *orig_buf = c;
|
|
|
+ --buf;
|
|
|
+ ++orig_buf;
|
|
|
+ }
|
|
|
+
|
|
|
+ return n_write;
|
|
|
+}
|
|
|
+
|
|
|
ssize_t
|
|
|
snprint_hex(
|
|
|
char* buf,
|
|
@@ -166,7 +263,7 @@ snprintf(
|
|
|
|
|
|
// int32 decimal
|
|
|
case 'd':
|
|
|
- n_tmp_write = snprint_decimal(buf, buf_size, *(int32_t*)arg_ptr);
|
|
|
+ n_tmp_write = snprint_decimal32(buf, buf_size, *(int32_t*)arg_ptr);
|
|
|
arg_ptr += sizeof(int32_t);
|
|
|
break;
|
|
|
|
|
@@ -180,6 +277,23 @@ snprintf(
|
|
|
arg_ptr += sizeof(uint32_t);
|
|
|
break;
|
|
|
|
|
|
+ // long decimal
|
|
|
+ case 'l':
|
|
|
+ switch (*(++fmt)) {
|
|
|
+ // long long aka int64
|
|
|
+ case 'l':
|
|
|
+ ++fmt;
|
|
|
+ n_tmp_write = snprint_decimal64(buf, buf_size, *(int64_t*)arg_ptr);
|
|
|
+ arg_ptr += sizeof(int64_t);
|
|
|
+ break;
|
|
|
+ // long int aka int32
|
|
|
+ case 'd':
|
|
|
+ n_tmp_write = snprint_decimal32(buf, buf_size, *(int32_t*)arg_ptr);
|
|
|
+ arg_ptr += sizeof(int32_t);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
// c string
|
|
|
case 's':
|
|
|
n_tmp_write = snprintf(buf, buf_size, *(const char**)arg_ptr);
|