return str.{ data = c + 1, count = len };
}
+u64_to_str :: (n: u64, base: u64, buf: [] u8, min_length := 0, prefix := false) -> str {
+ c := ^buf[buf.count - 1];
+ len := 0;
+
+ BASE64_MAP := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
+
+ while n > 0 {
+ m := cast(u64) n % base;
+
+ *c = BASE64_MAP[cast(u32) m];
+ len += 1;
+ c -= 1;
+
+ n /= base;
+
+ } else {
+ *c = #char "0";
+ len += 1;
+ c -= 1;
+ }
+
+ if min_length > 0 && len < min_length {
+ for i: min_length - len {
+ *c = #char "0";
+ len += 1;
+ c -= 1;
+ }
+ }
+
+ if prefix {
+ if base == 16 {
+ *c = #char "x";
+ len += 1;
+ c -= 1;
+ *c = #char "0";
+ len += 1;
+ c -= 1;
+ }
+
+ if base == 2 {
+ *c = #char "b";
+ len += 1;
+ c -= 1;
+ *c = #char "0";
+ len += 1;
+ c -= 1;
+ }
+ }
+
+ return str.{ data = c + 1, count = len };
+}
+
// This is better than what used to be, but still relies on converting the integer
// part of the float to an integer, which could overflow.
f64_to_str :: (f: f64, buf: [] u8, digits_after_decimal := 4) -> str {
}
}
+ uint_case :: macro (T: type_expr) {
+ case T {
+ value := *(cast(^T) v.data);
+
+ ibuf : [128] u8;
+ istr := u64_to_str(~~value, formatting.base, ~~ibuf, min_length=formatting.minimum_width);
+ output->write(istr);
+ }
+ }
+
int_case(i8);
int_case(i16);
- int_case(u16);
int_case(i32);
- int_case(u32);
int_case(i64);
- int_case(u64);
+ uint_case(u16);
+ uint_case(u32);
+ uint_case(u64);
case f32 {
value := *(cast(^f32) v.data);
VAL(instr.r).dtype = instr.stype; \
break;
- OVM_IMM(OVM_TYPE_I8, i8, i)
- OVM_IMM(OVM_TYPE_I16, i16, i)
- OVM_IMM(OVM_TYPE_I32, i32, i)
- OVM_IMM(OVM_TYPE_I64, i64, l)
+ OVM_IMM(OVM_TYPE_I8, u8, i)
+ OVM_IMM(OVM_TYPE_I16, u16, i)
+ OVM_IMM(OVM_TYPE_I32, u32, i)
+ OVM_IMM(OVM_TYPE_I64, u64, l)
OVM_IMM(OVM_TYPE_F32, f32, f)
OVM_IMM(OVM_TYPE_F64, f64, d)
break; \
}
- OVM_LOAD(OVM_TYPE_I8, i8)
- OVM_LOAD(OVM_TYPE_I16, i16)
- OVM_LOAD(OVM_TYPE_I32, i32)
- OVM_LOAD(OVM_TYPE_I64, i64)
+ OVM_LOAD(OVM_TYPE_I8, u8)
+ OVM_LOAD(OVM_TYPE_I16, u16)
+ OVM_LOAD(OVM_TYPE_I32, u32)
+ OVM_LOAD(OVM_TYPE_I64, u64)
OVM_LOAD(OVM_TYPE_F32, f32)
OVM_LOAD(OVM_TYPE_F64, f64)
*(stype *) &((u8 *) engine->memory)[VAL(instr.r).u32 + (u32) instr.b] = VAL(instr.a).stype; \
break;
- OVM_STORE(OVM_TYPE_I8, i8)
- OVM_STORE(OVM_TYPE_I16, i16)
- OVM_STORE(OVM_TYPE_I32, i32)
- OVM_STORE(OVM_TYPE_I64, i64)
+ OVM_STORE(OVM_TYPE_I8, u8)
+ OVM_STORE(OVM_TYPE_I16, u16)
+ OVM_STORE(OVM_TYPE_I32, u32)
+ OVM_STORE(OVM_TYPE_I64, u64)
OVM_STORE(OVM_TYPE_F32, f32)
OVM_STORE(OVM_TYPE_F64, f64)
}
case 0x41: {
- long long value = leb128_to_int(ctx->binary.data, &ctx->offset);
+ i64 value = leb128_to_int(ctx->binary.data, &ctx->offset);
// NOTE: This assumes a little-endian CPU as the address is assumes
// to be the least significant byte.
}
case 0x42: {
- long long value = leb128_to_int(ctx->binary.data, &ctx->offset);
+ i64 value = leb128_to_int(ctx->binary.data, &ctx->offset);
ovm_code_builder_add_imm(&ctx->builder, OVM_TYPE_I64, &value);
break;
}
}
BH_DEF i64 leb128_to_int(u8* bytes, i32 *byte_count) {
- i64 res = 0;
+ u64 res = 0;
u64 shift = 0;
u64 size = 64;
u8 byte;
do {
byte = bytes[(*byte_count)++];
- res |= (byte & 0x7f) << shift;
+ res |= ((u64) (byte & 0x7f)) << shift;
shift += 7;
} while ((byte & 0x80) != 0);
if ((shift < size) && (byte & 0x40) != 0) {
- i64 zero_shifted = ~ 0x0;
+ u64 zero_shifted = ~ 0x0;
zero_shifted = zero_shifted << shift;
return res | zero_shifted;
}