OP_DIV_R,
OP_DIV_U,
OP_DIV_U_R,
+ OP_MOD,
+ OP_MOD_R,
+ OP_MOD_U,
+ OP_MOD_U_R,
OP_SHL_I8,
OP_SHL_I16,
OP_SHL_I32,
"div.r",
"div.u",
"div.u.r",
+ "mod",
+ "mod.r",
+ "mod.u",
+ "mod.u.r",
"shl.i8",
"shl.i16",
"shl.i32",
iy = 0;
while (true) {
enum op op = (uint8_t)mem->i8[pc++ & mem_mask];
- //fprintf(stderr, "w=%08x(%d) sp=%08x(%08x) pc=%08x(%02x %s)\n", w_reg.i32, w_type, sp, mem->i32[sp >> 2], pc - 1, op, op < N_OP ? mnemonics[op] : "???");
+ //fprintf(stderr, "w=%08x(%d) sp=%08x ix=%08x iy=%08x pc=%08x(%02x %s)\n", w_reg.i32, w_type, sp, ix, iy, pc - 1, op, op < N_OP ? mnemonics[op] : "???");
switch (op) {
// w register access
case OP_IMM_I8:
case OP_SUB:
switch (w_type) {
case W_TYPE_I8:
- w_reg.i8 -= mem->i8[sp++ & mem_mask];
+ w_reg.i8 = mem->i8[sp++ & mem_mask] - w_reg.i8;
break;
case W_TYPE_I16:
sp = (sp + 1) & ~1;
- w_reg.i16 -= mem->i16[(sp & mem_mask) >> 1];
+ w_reg.i16 = mem->i16[(sp & mem_mask) >> 1] - w_reg.i16;
sp += 2;
break;
case W_TYPE_I32:
sp = (sp + 3) & ~3;
- w_reg.i32 -= mem->i32[(sp & mem_mask) >> 2];
+ w_reg.i32 = mem->i32[(sp & mem_mask) >> 2] - w_reg.i32;
sp += 4;
break;
case W_TYPE_I64:
sp = (sp + 7) & ~7;
- w_reg.i64 -= mem->i64[(sp & mem_mask) >> 3];
+ w_reg.i64 = mem->i64[(sp & mem_mask) >> 3] - w_reg.i64;
sp += 8;
break;
case W_TYPE_I128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i128 -= mem->i128[(sp & mem_mask) >> 4];
+ w_reg.i128 = mem->i128[(sp & mem_mask) >> 4] - w_reg.i128;
sp += 0x10;
break;
case W_TYPE_F32:
sp = (sp + 3) & ~3;
- w_reg.f32 -= mem->f32[(sp & mem_mask) >> 2];
+ w_reg.f32 = mem->f32[(sp & mem_mask) >> 2] - w_reg.f32;
sp += 4;
break;
case W_TYPE_F64:
sp = (sp + 7) & ~7;
- w_reg.f64 -= mem->f64[(sp & mem_mask) >> 3];
+ w_reg.f64 = mem->f64[(sp & mem_mask) >> 3] - w_reg.f64;
sp += 8;
break;
case W_TYPE_F128:
sp = (sp + 0xf) & ~0xf;
- w_reg.f128 -= mem->f128[(sp & mem_mask) >> 4];
+ w_reg.f128 = mem->f128[(sp & mem_mask) >> 4] - w_reg.f128;
sp += 0x10;
break;
default:
case OP_SUB_R:
switch (w_type) {
case W_TYPE_I8:
- w_reg.i8 = mem->i8[sp++ & mem_mask] - w_reg.i8;
+ w_reg.i8 -= mem->i8[sp++ & mem_mask];
break;
case W_TYPE_I16:
sp = (sp + 1) & ~1;
- w_reg.i16 = mem->i16[(sp & mem_mask) >> 1] - w_reg.i16;
+ w_reg.i16 -= mem->i16[(sp & mem_mask) >> 1];
sp += 2;
break;
case W_TYPE_I32:
sp = (sp + 3) & ~3;
- w_reg.i32 = mem->i32[(sp & mem_mask) >> 2] - w_reg.i32;
+ w_reg.i32 -= mem->i32[(sp & mem_mask) >> 2];
sp += 4;
break;
case W_TYPE_I64:
sp = (sp + 7) & ~7;
- w_reg.i64 = mem->i64[(sp & mem_mask) >> 3] - w_reg.i64;
+ w_reg.i64 -= mem->i64[(sp & mem_mask) >> 3];
sp += 8;
break;
case W_TYPE_I128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i128 = mem->i128[(sp & mem_mask) >> 4] - w_reg.i128;
+ w_reg.i128 -= mem->i128[(sp & mem_mask) >> 4];
sp += 0x10;
break;
case W_TYPE_F32:
sp = (sp + 3) & ~3;
- w_reg.f32 = mem->f32[(sp & mem_mask) >> 2] - w_reg.f32;
+ w_reg.f32 -= mem->f32[(sp & mem_mask) >> 2];
sp += 4;
break;
case W_TYPE_F64:
sp = (sp + 7) & ~7;
- w_reg.f64 = mem->f64[(sp & mem_mask) >> 3] - w_reg.f64;
+ w_reg.f64 -= mem->f64[(sp & mem_mask) >> 3];
sp += 8;
break;
case W_TYPE_F128:
sp = (sp + 0xf) & ~0xf;
- w_reg.f128 = mem->f128[(sp & mem_mask) >> 4] - w_reg.f128;
+ w_reg.f128 -= mem->f128[(sp & mem_mask) >> 4];
sp += 0x10;
break;
default:
case OP_DIV:
switch (w_type) {
case W_TYPE_I8:
- w_reg.i8 /= mem->i8[sp++ & mem_mask];
+ w_reg.i8 = mem->i8[sp++ & mem_mask] / w_reg.i8;
break;
case W_TYPE_I16:
sp = (sp + 1) & ~1;
- w_reg.i16 /= mem->i16[(sp & mem_mask) >> 1];
+ w_reg.i16 = mem->i16[(sp & mem_mask) >> 1] / w_reg.i16;
sp += 2;
break;
case W_TYPE_I32:
sp = (sp + 3) & ~3;
- w_reg.i32 /= mem->i32[(sp & mem_mask) >> 2];
+ w_reg.i32 = mem->i32[(sp & mem_mask) >> 2] / w_reg.i32;
sp += 4;
break;
case W_TYPE_I64:
sp = (sp + 7) & ~7;
- w_reg.i64 /= mem->i64[(sp & mem_mask) >> 3];
+ w_reg.i64 = mem->i64[(sp & mem_mask) >> 3] / w_reg.i64;
sp += 8;
break;
case W_TYPE_I128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i128 /= mem->i128[(sp & mem_mask) >> 4];
+ w_reg.i128 = mem->i128[(sp & mem_mask) >> 4] / w_reg.i128;
sp += 0x10;
break;
case W_TYPE_F32:
sp = (sp + 3) & ~3;
- w_reg.f32 /= mem->f32[(sp & mem_mask) >> 2];
+ w_reg.f32 = mem->f32[(sp & mem_mask) >> 2] / w_reg.f32;
sp += 4;
break;
case W_TYPE_F64:
sp = (sp + 7) & ~7;
- w_reg.f64 /= mem->f64[(sp & mem_mask) >> 3];
+ w_reg.f64 = mem->f64[(sp & mem_mask) >> 3] / w_reg.f64;
sp += 8;
break;
case W_TYPE_F128:
sp = (sp + 0xf) & ~0xf;
- w_reg.f128 /= mem->f128[(sp & mem_mask) >> 4];
+ w_reg.f128 = mem->f128[(sp & mem_mask) >> 4] / w_reg.f128;
sp += 0x10;
break;
default:
case OP_DIV_R:
switch (w_type) {
case W_TYPE_I8:
- w_reg.i8 = mem->i8[sp++ & mem_mask] / w_reg.i8;
+ w_reg.i8 /= mem->i8[sp++ & mem_mask];
break;
case W_TYPE_I16:
sp = (sp + 1) & ~1;
- w_reg.i16 = mem->i16[(sp & mem_mask) >> 1] / w_reg.i16;
+ w_reg.i16 /= mem->i16[(sp & mem_mask) >> 1];
sp += 2;
break;
case W_TYPE_I32:
sp = (sp + 3) & ~3;
- w_reg.i32 = mem->i32[(sp & mem_mask) >> 2] / w_reg.i32;
+ w_reg.i32 /= mem->i32[(sp & mem_mask) >> 2];
sp += 4;
break;
case W_TYPE_I64:
sp = (sp + 7) & ~7;
- w_reg.i64 = mem->i64[(sp & mem_mask) >> 3] / w_reg.i64;
+ w_reg.i64 /= mem->i64[(sp & mem_mask) >> 3];
sp += 8;
break;
case W_TYPE_I128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i128 = mem->i128[(sp & mem_mask) >> 4] / w_reg.i128;
+ w_reg.i128 /= mem->i128[(sp & mem_mask) >> 4];
sp += 0x10;
break;
case W_TYPE_F32:
sp = (sp + 3) & ~3;
- w_reg.f32 = mem->f32[(sp & mem_mask) >> 2] / w_reg.f32;
+ w_reg.f32 /= mem->f32[(sp & mem_mask) >> 2];
sp += 4;
break;
case W_TYPE_F64:
sp = (sp + 7) & ~7;
- w_reg.f64 = mem->f64[(sp & mem_mask) >> 3] / w_reg.f64;
+ w_reg.f64 /= mem->f64[(sp & mem_mask) >> 3];
sp += 8;
break;
case W_TYPE_F128:
sp = (sp + 0xf) & ~0xf;
- w_reg.f128 = mem->f128[(sp & mem_mask) >> 4] / w_reg.f128;
+ w_reg.f128 /= mem->f128[(sp & mem_mask) >> 4];
sp += 0x10;
break;
default:
}
break;
case OP_DIV_U:
+ switch (w_type) {
+ case W_TYPE_I8:
+ w_reg.i8 = (int8_t)((uint8_t)mem->i8[sp++ & mem_mask] / (uint8_t)w_reg.i8);
+ break;
+ case W_TYPE_I16:
+ sp = (sp + 1) & ~1;
+ w_reg.i16 = (int16_t)((uint16_t)mem->i16[(sp & mem_mask) >> 1] / (uint16_t)w_reg.i16);
+ sp += 2;
+ break;
+ case W_TYPE_I32:
+ sp = (sp + 3) & ~3;
+ w_reg.i32 = (int32_t)((uint32_t)mem->i32[(sp & mem_mask) >> 2] / (uint32_t)w_reg.i32);
+ sp += 4;
+ break;
+ case W_TYPE_I64:
+ sp = (sp + 7) & ~7;
+ w_reg.i64 = (int64_t)((uint64_t)mem->i64[(sp & mem_mask) >> 3] / (uint64_t)w_reg.i64);
+ sp += 8;
+ break;
+ case W_TYPE_I128:
+ sp = (sp + 0xf) & ~0xf;
+ w_reg.i128 = (int128_t)((uint128_t)mem->i128[(sp & mem_mask) >> 4] / (uint128_t)w_reg.i128);
+ sp += 0x10;
+ break;
+ default:
+ abort();
+ }
+ break;
+ case OP_DIV_U_R:
switch (w_type) {
case W_TYPE_I8:
w_reg.i8 = (int8_t)((uint8_t)w_reg.i8 / (uint8_t)mem->i8[sp++ & mem_mask]);
abort();
}
break;
- case OP_DIV_U_R:
+ case OP_MOD:
switch (w_type) {
case W_TYPE_I8:
- w_reg.i8 = (int8_t)((uint8_t)mem->i8[sp++ & mem_mask] / (uint8_t)w_reg.i8);
+ w_reg.i8 = mem->i8[sp++ & mem_mask] % w_reg.i8;
break;
case W_TYPE_I16:
sp = (sp + 1) & ~1;
- w_reg.i16 = (int16_t)((uint16_t)mem->i16[(sp & mem_mask) >> 1] / (uint16_t)w_reg.i16);
+ w_reg.i16 = mem->i16[(sp & mem_mask) >> 1] % w_reg.i16;
sp += 2;
break;
case W_TYPE_I32:
sp = (sp + 3) & ~3;
- w_reg.i32 = (int32_t)((uint32_t)mem->i32[(sp & mem_mask) >> 2] / (uint32_t)w_reg.i32);
+ w_reg.i32 = mem->i32[(sp & mem_mask) >> 2] % w_reg.i32;
sp += 4;
break;
case W_TYPE_I64:
sp = (sp + 7) & ~7;
- w_reg.i64 = (int64_t)((uint64_t)mem->i64[(sp & mem_mask) >> 3] / (uint64_t)w_reg.i64);
+ w_reg.i64 = mem->i64[(sp & mem_mask) >> 3] % w_reg.i64;
sp += 8;
break;
case W_TYPE_I128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i128 = (int128_t)((uint128_t)mem->i128[(sp & mem_mask) >> 4] / (uint128_t)w_reg.i128);
+ w_reg.i128 = mem->i128[(sp & mem_mask) >> 4] % w_reg.i128;
+ sp += 0x10;
+ break;
+ default:
+ abort();
+ }
+ break;
+ case OP_MOD_R:
+ switch (w_type) {
+ case W_TYPE_I8:
+ w_reg.i8 %= mem->i8[sp++ & mem_mask];
+ break;
+ case W_TYPE_I16:
+ sp = (sp + 1) & ~1;
+ w_reg.i16 %= mem->i16[(sp & mem_mask) >> 1];
+ sp += 2;
+ break;
+ case W_TYPE_I32:
+ sp = (sp + 3) & ~3;
+ w_reg.i32 %= mem->i32[(sp & mem_mask) >> 2];
+ sp += 4;
+ break;
+ case W_TYPE_I64:
+ sp = (sp + 7) & ~7;
+ w_reg.i64 %= mem->i64[(sp & mem_mask) >> 3];
+ sp += 8;
+ break;
+ case W_TYPE_I128:
+ sp = (sp + 0xf) & ~0xf;
+ w_reg.i128 %= mem->i128[(sp & mem_mask) >> 4];
+ sp += 0x10;
+ break;
+ default:
+ abort();
+ }
+ break;
+ case OP_MOD_U:
+ switch (w_type) {
+ case W_TYPE_I8:
+ w_reg.i8 = (int8_t)((uint8_t)mem->i8[sp++ & mem_mask] % (uint8_t)w_reg.i8);
+ break;
+ case W_TYPE_I16:
+ sp = (sp + 1) & ~1;
+ w_reg.i16 = (int16_t)((uint16_t)mem->i16[(sp & mem_mask) >> 1] % (uint16_t)w_reg.i16);
+ sp += 2;
+ break;
+ case W_TYPE_I32:
+ sp = (sp + 3) & ~3;
+ w_reg.i32 = (int32_t)((uint32_t)mem->i32[(sp & mem_mask) >> 2] % (uint32_t)w_reg.i32);
+ sp += 4;
+ break;
+ case W_TYPE_I64:
+ sp = (sp + 7) & ~7;
+ w_reg.i64 = (int64_t)((uint64_t)mem->i64[(sp & mem_mask) >> 3] % (uint64_t)w_reg.i64);
+ sp += 8;
+ break;
+ case W_TYPE_I128:
+ sp = (sp + 0xf) & ~0xf;
+ w_reg.i128 = (int128_t)((uint128_t)mem->i128[(sp & mem_mask) >> 4] % (uint128_t)w_reg.i128);
+ sp += 0x10;
+ break;
+ default:
+ abort();
+ }
+ break;
+ case OP_MOD_U_R:
+ switch (w_type) {
+ case W_TYPE_I8:
+ w_reg.i8 = (int8_t)((uint8_t)w_reg.i8 % (uint8_t)mem->i8[sp++ & mem_mask]);
+ break;
+ case W_TYPE_I16:
+ sp = (sp + 1) & ~1;
+ w_reg.i16 = (int16_t)((uint16_t)w_reg.i16 % (uint16_t)mem->i16[(sp & mem_mask) >> 1]);
+ sp += 2;
+ break;
+ case W_TYPE_I32:
+ sp = (sp + 3) & ~3;
+ w_reg.i32 = (int32_t)((uint32_t)w_reg.i32 % (uint32_t)mem->i32[(sp & mem_mask) >> 2]);
+ sp += 4;
+ break;
+ case W_TYPE_I64:
+ sp = (sp + 7) & ~7;
+ w_reg.i64 = (int64_t)((uint64_t)w_reg.i64 % (uint64_t)mem->i64[(sp & mem_mask) >> 3]);
+ sp += 8;
+ break;
+ case W_TYPE_I128:
+ sp = (sp + 0xf) & ~0xf;
+ w_reg.i128 = (int128_t)((uint128_t)w_reg.i128 % (uint128_t)mem->i128[(sp & mem_mask) >> 4]);
sp += 0x10;
break;
default:
case OP_EQ:
switch (w_type) {
case W_TYPE_I8:
- w_reg.i8 = w_reg.i8 == mem->i8[sp++ & mem_mask];
+ w_reg.i8 = mem->i8[sp++ & mem_mask] == w_reg.i8;
break;
case W_TYPE_I16:
sp = (sp + 1) & ~1;
- w_reg.i8 = w_reg.i16 == mem->i16[(sp & mem_mask) >> 1];
+ w_reg.i8 = mem->i16[(sp & mem_mask) >> 1] == w_reg.i16;
sp += 2;
break;
case W_TYPE_I32:
sp = (sp + 3) & ~3;
- w_reg.i8 = w_reg.i32 == mem->i32[(sp & mem_mask) >> 2];
+ w_reg.i8 = mem->i32[(sp & mem_mask) >> 2] == w_reg.i32;
sp += 4;
break;
case W_TYPE_I64:
sp = (sp + 7) & ~7;
- w_reg.i8 = w_reg.i64 == mem->i64[(sp & mem_mask) >> 3];
+ w_reg.i8 = mem->i64[(sp & mem_mask) >> 3] == w_reg.i64;
sp += 8;
break;
case W_TYPE_I128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i8 = w_reg.i128 == mem->i128[(sp & mem_mask) >> 4];
+ w_reg.i8 = mem->i128[(sp & mem_mask) >> 4] == w_reg.i128;
sp += 0x10;
break;
case W_TYPE_F32:
sp = (sp + 3) & ~3;
- w_reg.i8 = w_reg.f32 == mem->f32[(sp & mem_mask) >> 2];
+ w_reg.i8 = mem->f32[(sp & mem_mask) >> 2] == w_reg.f32;
sp += 4;
break;
case W_TYPE_F64:
sp = (sp + 7) & ~7;
- w_reg.i8 = w_reg.f64 == mem->f64[(sp & mem_mask) >> 3];
+ w_reg.i8 = mem->f64[(sp & mem_mask) >> 3] == w_reg.f64;
sp += 8;
break;
case W_TYPE_F128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i8 = w_reg.f128 == mem->f128[(sp & mem_mask) >> 4];
+ w_reg.i8 = mem->f128[(sp & mem_mask) >> 4] == w_reg.f128;
sp += 0x10;
break;
default:
case OP_NE:
switch (w_type) {
case W_TYPE_I8:
- w_reg.i8 = w_reg.i8 != mem->i8[sp++ & mem_mask];
+ w_reg.i8 = mem->i8[sp++ & mem_mask] != w_reg.i8;
break;
case W_TYPE_I16:
sp = (sp + 1) & ~1;
- w_reg.i8 = w_reg.i16 != mem->i16[(sp & mem_mask) >> 1];
+ w_reg.i8 = mem->i16[(sp & mem_mask) >> 1] != w_reg.i16;
sp += 2;
break;
case W_TYPE_I32:
sp = (sp + 3) & ~3;
- w_reg.i8 = w_reg.i32 != mem->i32[(sp & mem_mask) >> 2];
+ w_reg.i8 = mem->i32[(sp & mem_mask) >> 2] != w_reg.i32;
sp += 4;
break;
case W_TYPE_I64:
sp = (sp + 7) & ~7;
- w_reg.i8 = w_reg.i64 != mem->i64[(sp & mem_mask) >> 3];
+ w_reg.i8 = mem->i64[(sp & mem_mask) >> 3] != w_reg.i64;
sp += 8;
break;
case W_TYPE_I128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i8 = w_reg.i128 != mem->i128[(sp & mem_mask) >> 4];
+ w_reg.i8 = mem->i128[(sp & mem_mask) >> 4] != w_reg.i128;
sp += 0x10;
break;
case W_TYPE_F32:
sp = (sp + 3) & ~3;
- w_reg.i8 = w_reg.f32 != mem->f32[(sp & mem_mask) >> 2];
+ w_reg.i8 = mem->f32[(sp & mem_mask) >> 2] != w_reg.f32;
sp += 4;
break;
case W_TYPE_F64:
sp = (sp + 7) & ~7;
- w_reg.i8 = w_reg.f64 != mem->f64[(sp & mem_mask) >> 3];
+ w_reg.i8 = mem->f64[(sp & mem_mask) >> 3] != w_reg.f64;
sp += 8;
break;
case W_TYPE_F128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i8 = w_reg.f128 != mem->f128[(sp & mem_mask) >> 4];
+ w_reg.i8 = mem->f128[(sp & mem_mask) >> 4] != w_reg.f128;
sp += 0x10;
break;
default:
case OP_LT:
switch (w_type) {
case W_TYPE_I8:
- w_reg.i8 = w_reg.i8 < mem->i8[sp++ & mem_mask];
+ w_reg.i8 = mem->i8[sp++ & mem_mask] < w_reg.i8;
break;
case W_TYPE_I16:
sp = (sp + 1) & ~1;
- w_reg.i8 = w_reg.i16 < mem->i16[(sp & mem_mask) >> 1];
+ w_reg.i8 = mem->i16[(sp & mem_mask) >> 1] < w_reg.i16;
sp += 2;
break;
case W_TYPE_I32:
sp = (sp + 3) & ~3;
- w_reg.i8 = w_reg.i32 < mem->i32[(sp & mem_mask) >> 2];
+ w_reg.i8 = mem->i32[(sp & mem_mask) >> 2] < w_reg.i32;
sp += 4;
break;
case W_TYPE_I64:
sp = (sp + 7) & ~7;
- w_reg.i8 = w_reg.i64 < mem->i64[(sp & mem_mask) >> 3];
+ w_reg.i8 = mem->i64[(sp & mem_mask) >> 3] < w_reg.i64;
sp += 8;
break;
case W_TYPE_I128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i8 = w_reg.i128 < mem->i128[(sp & mem_mask) >> 4];
+ w_reg.i8 = mem->i128[(sp & mem_mask) >> 4] < w_reg.i128;
sp += 0x10;
break;
case W_TYPE_F32:
sp = (sp + 3) & ~3;
- w_reg.i8 = w_reg.f32 < mem->f32[(sp & mem_mask) >> 2];
+ w_reg.i8 = mem->f32[(sp & mem_mask) >> 2] < w_reg.f32;
sp += 4;
break;
case W_TYPE_F64:
sp = (sp + 7) & ~7;
- w_reg.i8 = w_reg.f64 < mem->f64[(sp & mem_mask) >> 3];
+ w_reg.i8 = mem->f64[(sp & mem_mask) >> 3] < w_reg.f64;
sp += 8;
break;
case W_TYPE_F128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i8 = w_reg.f128 < mem->f128[(sp & mem_mask) >> 4];
+ w_reg.i8 = mem->f128[(sp & mem_mask) >> 4] < w_reg.f128;
sp += 0x10;
break;
default:
case OP_LT_U:
switch (w_type) {
case W_TYPE_I8:
- w_reg.i8 = (uint8_t)w_reg.i8 < (uint8_t)mem->i8[sp++ & mem_mask];
+ w_reg.i8 = (uint8_t)mem->i8[sp++ & mem_mask] < (uint8_t)w_reg.i8;
break;
case W_TYPE_I16:
sp = (sp + 1) & ~1;
- w_reg.i8 = (uint16_t)w_reg.i16 < (uint16_t)mem->i16[(sp & mem_mask) >> 1];
+ w_reg.i8 = (uint16_t)mem->i16[(sp & mem_mask) >> 1] < (uint16_t)w_reg.i16;
sp += 2;
break;
case W_TYPE_I32:
sp = (sp + 3) & ~3;
- w_reg.i8 = (uint32_t)w_reg.i32 < (uint32_t)mem->i32[(sp & mem_mask) >> 2];
+ w_reg.i8 = (uint32_t)mem->i32[(sp & mem_mask) >> 2] < (uint32_t)w_reg.i32;
sp += 4;
break;
case W_TYPE_I64:
sp = (sp + 7) & ~7;
- w_reg.i8 = (uint64_t)w_reg.i64 < (uint64_t)mem->i64[(sp & mem_mask) >> 3];
+ w_reg.i8 = (uint64_t)mem->i64[(sp & mem_mask) >> 3] < (uint64_t)w_reg.i64;
sp += 8;
break;
case W_TYPE_I128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i8 = (uint128_t)w_reg.i128 < (uint128_t)mem->i128[(sp & mem_mask) >> 4];
+ w_reg.i8 = (uint128_t)mem->i128[(sp & mem_mask) >> 4] < (uint128_t)w_reg.i128;
sp += 0x10;
break;
default:
case OP_LE:
switch (w_type) {
case W_TYPE_I8:
- w_reg.i8 = w_reg.i8 <= mem->i8[sp++ & mem_mask];
+ w_reg.i8 = mem->i8[sp++ & mem_mask] <= w_reg.i8;
break;
case W_TYPE_I16:
sp = (sp + 1) & ~1;
- w_reg.i8 = w_reg.i16 <= mem->i16[(sp & mem_mask) >> 1];
+ w_reg.i8 = mem->i16[(sp & mem_mask) >> 1] <= w_reg.i16;
sp += 2;
break;
case W_TYPE_I32:
sp = (sp + 3) & ~3;
- w_reg.i8 = w_reg.i32 <= mem->i32[(sp & mem_mask) >> 2];
+ w_reg.i8 = mem->i32[(sp & mem_mask) >> 2] <= w_reg.i32;
sp += 4;
break;
case W_TYPE_I64:
sp = (sp + 7) & ~7;
- w_reg.i8 = w_reg.i64 <= mem->i64[(sp & mem_mask) >> 3];
+ w_reg.i8 = mem->i64[(sp & mem_mask) >> 3] <= w_reg.i64;
sp += 8;
break;
case W_TYPE_I128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i8 = w_reg.i128 <= mem->i128[(sp & mem_mask) >> 4];
+ w_reg.i8 = mem->i128[(sp & mem_mask) >> 4] <= w_reg.i128;
sp += 0x10;
break;
case W_TYPE_F32:
sp = (sp + 3) & ~3;
- w_reg.i8 = w_reg.f32 <= mem->f32[(sp & mem_mask) >> 2];
+ w_reg.i8 = mem->f32[(sp & mem_mask) >> 2] <= w_reg.f32;
sp += 4;
break;
case W_TYPE_F64:
sp = (sp + 7) & ~7;
- w_reg.i8 = w_reg.f64 <= mem->f64[(sp & mem_mask) >> 3];
+ w_reg.i8 = mem->f64[(sp & mem_mask) >> 3] <= w_reg.f64;
sp += 8;
break;
case W_TYPE_F128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i8 = w_reg.f128 <= mem->f128[(sp & mem_mask) >> 4];
+ w_reg.i8 = mem->f128[(sp & mem_mask) >> 4] <= w_reg.f128;
sp += 0x10;
break;
default:
case OP_LE_U:
switch (w_type) {
case W_TYPE_I8:
- w_reg.i8 = (uint8_t)w_reg.i8 <= (uint8_t)mem->i8[sp++ & mem_mask];
+ w_reg.i8 = (uint8_t)mem->i8[sp++ & mem_mask] <= (uint8_t)w_reg.i8;
break;
case W_TYPE_I16:
sp = (sp + 1) & ~1;
- w_reg.i8 = (uint16_t)w_reg.i16 <= (uint16_t)mem->i16[(sp & mem_mask) >> 1];
+ w_reg.i8 = (uint16_t)mem->i16[(sp & mem_mask) >> 1] <= (uint16_t)w_reg.i16;
sp += 2;
break;
case W_TYPE_I32:
sp = (sp + 3) & ~3;
- w_reg.i8 = (uint32_t)w_reg.i32 <= (uint32_t)mem->i32[(sp & mem_mask) >> 2];
+ w_reg.i8 = (uint32_t)mem->i32[(sp & mem_mask) >> 2] <= (uint32_t)w_reg.i32;
sp += 4;
break;
case W_TYPE_I64:
sp = (sp + 7) & ~7;
- w_reg.i8 = (uint64_t)w_reg.i64 <= (uint64_t)mem->i64[(sp & mem_mask) >> 3];
+ w_reg.i8 = (uint64_t)mem->i64[(sp & mem_mask) >> 3] <= (uint64_t)w_reg.i64;
sp += 8;
break;
case W_TYPE_I128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i8 = (uint128_t)w_reg.i128 <= (uint128_t)mem->i128[(sp & mem_mask) >> 4];
+ w_reg.i8 = (uint128_t)mem->i128[(sp & mem_mask) >> 4] <= (uint128_t)w_reg.i128;
sp += 0x10;
break;
default:
case OP_GT:
switch (w_type) {
case W_TYPE_I8:
- w_reg.i8 = w_reg.i8 > mem->i8[sp++ & mem_mask];
+ w_reg.i8 = mem->i8[sp++ & mem_mask] > w_reg.i8;
break;
case W_TYPE_I16:
sp = (sp + 1) & ~1;
- w_reg.i8 = w_reg.i16 > mem->i16[(sp & mem_mask) >> 1];
+ w_reg.i8 = mem->i16[(sp & mem_mask) >> 1] > w_reg.i16;
sp += 2;
break;
case W_TYPE_I32:
sp = (sp + 3) & ~3;
- w_reg.i8 = w_reg.i32 > mem->i32[(sp & mem_mask) >> 2];
+ w_reg.i8 = mem->i32[(sp & mem_mask) >> 2] > w_reg.i32;
sp += 4;
break;
case W_TYPE_I64:
sp = (sp + 7) & ~7;
- w_reg.i8 = w_reg.i64 > mem->i64[(sp & mem_mask) >> 3];
+ w_reg.i8 = mem->i64[(sp & mem_mask) >> 3] > w_reg.i64;
sp += 8;
break;
case W_TYPE_I128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i8 = w_reg.i128 > mem->i128[(sp & mem_mask) >> 4];
+ w_reg.i8 = mem->i128[(sp & mem_mask) >> 4] > w_reg.i128;
sp += 0x10;
break;
case W_TYPE_F32:
sp = (sp + 3) & ~3;
- w_reg.i8 = w_reg.f32 > mem->f32[(sp & mem_mask) >> 2];
+ w_reg.i8 = mem->f32[(sp & mem_mask) >> 2] > w_reg.f32;
sp += 4;
break;
case W_TYPE_F64:
sp = (sp + 7) & ~7;
- w_reg.i8 = w_reg.f64 > mem->f64[(sp & mem_mask) >> 3];
+ w_reg.i8 = mem->f64[(sp & mem_mask) >> 3] > w_reg.f64;
sp += 8;
break;
case W_TYPE_F128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i8 = w_reg.f128 > mem->f128[(sp & mem_mask) >> 4];
+ w_reg.i8 = mem->f128[(sp & mem_mask) >> 4] > w_reg.f128;
sp += 0x10;
break;
default:
case OP_GT_U:
switch (w_type) {
case W_TYPE_I8:
- w_reg.i8 = (uint8_t)w_reg.i8 > (uint8_t)mem->i8[sp++ & mem_mask];
+ w_reg.i8 = (uint8_t)mem->i8[sp++ & mem_mask] > (uint8_t)w_reg.i8;
break;
case W_TYPE_I16:
sp = (sp + 1) & ~1;
- w_reg.i8 = (uint16_t)w_reg.i16 > (uint16_t)mem->i16[(sp & mem_mask) >> 1];
+ w_reg.i8 = (uint16_t)mem->i16[(sp & mem_mask) >> 1] > (uint16_t)w_reg.i16;
sp += 2;
break;
case W_TYPE_I32:
sp = (sp + 3) & ~3;
- w_reg.i8 = (uint32_t)w_reg.i32 > (uint32_t)mem->i32[(sp & mem_mask) >> 2];
+ w_reg.i8 = (uint32_t)mem->i32[(sp & mem_mask) >> 2] > (uint32_t)w_reg.i32;
sp += 4;
break;
case W_TYPE_I64:
sp = (sp + 7) & ~7;
- w_reg.i8 = (uint64_t)w_reg.i64 > (uint64_t)mem->i64[(sp & mem_mask) >> 3];
+ w_reg.i8 = (uint64_t)mem->i64[(sp & mem_mask) >> 3] > (uint64_t)w_reg.i64;
sp += 8;
break;
case W_TYPE_I128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i8 = (uint128_t)w_reg.i128 > (uint128_t)mem->i128[(sp & mem_mask) >> 4];
+ w_reg.i8 = (uint128_t)mem->i128[(sp & mem_mask) >> 4] > (uint128_t)w_reg.i128;
sp += 0x10;
break;
default:
case OP_GE:
switch (w_type) {
case W_TYPE_I8:
- w_reg.i8 = w_reg.i8 >= mem->i8[sp++ & mem_mask];
+ w_reg.i8 = mem->i8[sp++ & mem_mask] >= w_reg.i8;
break;
case W_TYPE_I16:
sp = (sp + 1) & ~1;
- w_reg.i8 = w_reg.i16 >= mem->i16[(sp & mem_mask) >> 1];
+ w_reg.i8 = mem->i16[(sp & mem_mask) >> 1] >= w_reg.i16;
sp += 2;
break;
case W_TYPE_I32:
sp = (sp + 3) & ~3;
- w_reg.i8 = w_reg.i32 >= mem->i32[(sp & mem_mask) >> 2];
+ w_reg.i8 = mem->i32[(sp & mem_mask) >> 2] >= w_reg.i32;
sp += 4;
break;
case W_TYPE_I64:
sp = (sp + 7) & ~7;
- w_reg.i8 = w_reg.i64 >= mem->i64[(sp & mem_mask) >> 3];
+ w_reg.i8 = mem->i64[(sp & mem_mask) >> 3] >= w_reg.i64;
sp += 8;
break;
case W_TYPE_I128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i8 = w_reg.i128 >= mem->i128[(sp & mem_mask) >> 4];
+ w_reg.i8 = mem->i128[(sp & mem_mask) >> 4] >= w_reg.i128;
sp += 0x10;
break;
case W_TYPE_F32:
sp = (sp + 3) & ~3;
- w_reg.i8 = w_reg.f32 >= mem->f32[(sp & mem_mask) >> 2];
+ w_reg.i8 = mem->f32[(sp & mem_mask) >> 2] >= w_reg.f32;
sp += 4;
break;
case W_TYPE_F64:
sp = (sp + 7) & ~7;
- w_reg.i8 = w_reg.f64 >= mem->f64[(sp & mem_mask) >> 3];
+ w_reg.i8 = mem->f64[(sp & mem_mask) >> 3] >= w_reg.f64;
sp += 8;
break;
case W_TYPE_F128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i8 = w_reg.f128 >= mem->f128[(sp & mem_mask) >> 4];
+ w_reg.i8 = mem->f128[(sp & mem_mask) >> 4] >= w_reg.f128;
sp += 0x10;
break;
default:
case OP_GE_U:
switch (w_type) {
case W_TYPE_I8:
- w_reg.i8 = (uint8_t)w_reg.i8 >= (uint8_t)mem->i8[sp++ & mem_mask];
+ w_reg.i8 = (uint8_t)mem->i8[sp++ & mem_mask] >= (uint8_t)w_reg.i8;
break;
case W_TYPE_I16:
sp = (sp + 1) & ~1;
- w_reg.i8 = (uint16_t)w_reg.i16 >= (uint16_t)mem->i16[(sp & mem_mask) >> 1];
+ w_reg.i8 = (uint16_t)mem->i16[(sp & mem_mask) >> 1] >= (uint16_t)w_reg.i16;
sp += 2;
break;
case W_TYPE_I32:
sp = (sp + 3) & ~3;
- w_reg.i8 = (uint32_t)w_reg.i32 >= (uint32_t)mem->i32[(sp & mem_mask) >> 2];
+ w_reg.i8 = (uint32_t)mem->i32[(sp & mem_mask) >> 2] >= (uint32_t)w_reg.i32;
sp += 4;
break;
case W_TYPE_I64:
sp = (sp + 7) & ~7;
- w_reg.i8 = (uint64_t)w_reg.i64 >= (uint64_t)mem->i64[(sp & mem_mask) >> 3];
+ w_reg.i8 = (uint64_t)mem->i64[(sp & mem_mask) >> 3] >= (uint64_t)w_reg.i64;
sp += 8;
break;
case W_TYPE_I128:
sp = (sp + 0xf) & ~0xf;
- w_reg.i8 = (uint128_t)w_reg.i128 >= (uint128_t)mem->i128[(sp & mem_mask) >> 4];
+ w_reg.i8 = (uint128_t)mem->i128[(sp & mem_mask) >> 4] >= (uint128_t)w_reg.i128;
sp += 0x10;
break;
default:
'div.r': (0x57, OPERAND_TYPE_NONE),
'div.u': (0x58, OPERAND_TYPE_NONE),
'div.u.r': (0x59, OPERAND_TYPE_NONE),
- 'shl.i8': (0x5a, OPERAND_TYPE_NONE),
- 'shl.i16': (0x5b, OPERAND_TYPE_NONE),
- 'shl.i32': (0x5c, OPERAND_TYPE_NONE),
- 'shl.i64': (0x5d, OPERAND_TYPE_NONE),
- 'shl.i128': (0x5e, OPERAND_TYPE_NONE),
- 'shl.r': (0x5f, OPERAND_TYPE_NONE),
- 'shr.i8': (0x60, OPERAND_TYPE_NONE),
- 'shr.i16': (0x61, OPERAND_TYPE_NONE),
- 'shr.i32': (0x62, OPERAND_TYPE_NONE),
- 'shr.i64': (0x63, OPERAND_TYPE_NONE),
- 'shr.i128': (0x64, OPERAND_TYPE_NONE),
- 'shr.r': (0x65, OPERAND_TYPE_NONE),
- 'shr.u.i8': (0x66, OPERAND_TYPE_NONE),
- 'shr.u.i16': (0x67, OPERAND_TYPE_NONE),
- 'shr.u.i32': (0x68, OPERAND_TYPE_NONE),
- 'shr.u.i64': (0x69, OPERAND_TYPE_NONE),
- 'shr.u.i128': (0x6a, OPERAND_TYPE_NONE),
- 'shr.u.r': (0x6b, OPERAND_TYPE_NONE),
- 'neg': (0x6c, OPERAND_TYPE_NONE),
- 'and': (0x6d, OPERAND_TYPE_NONE),
- 'or': (0x6e, OPERAND_TYPE_NONE),
- 'xor': (0x6f, OPERAND_TYPE_NONE),
- 'not': (0x70, OPERAND_TYPE_NONE),
+ 'mod': (0x5a, OPERAND_TYPE_NONE),
+ 'mod.r': (0x5b, OPERAND_TYPE_NONE),
+ 'mod.u': (0x5c, OPERAND_TYPE_NONE),
+ 'mod.u.r': (0x5d, OPERAND_TYPE_NONE),
+ 'shl.i8': (0x5e, OPERAND_TYPE_NONE),
+ 'shl.i16': (0x5f, OPERAND_TYPE_NONE),
+ 'shl.i32': (0x60, OPERAND_TYPE_NONE),
+ 'shl.i64': (0x61, OPERAND_TYPE_NONE),
+ 'shl.i128': (0x62, OPERAND_TYPE_NONE),
+ 'shl.r': (0x63, OPERAND_TYPE_NONE),
+ 'shr.i8': (0x64, OPERAND_TYPE_NONE),
+ 'shr.i16': (0x65, OPERAND_TYPE_NONE),
+ 'shr.i32': (0x66, OPERAND_TYPE_NONE),
+ 'shr.i64': (0x67, OPERAND_TYPE_NONE),
+ 'shr.i128': (0x68, OPERAND_TYPE_NONE),
+ 'shr.r': (0x69, OPERAND_TYPE_NONE),
+ 'shr.u.i8': (0x6a, OPERAND_TYPE_NONE),
+ 'shr.u.i16': (0x6b, OPERAND_TYPE_NONE),
+ 'shr.u.i32': (0x6c, OPERAND_TYPE_NONE),
+ 'shr.u.i64': (0x6d, OPERAND_TYPE_NONE),
+ 'shr.u.i128': (0x6e, OPERAND_TYPE_NONE),
+ 'shr.u.r': (0x6f, OPERAND_TYPE_NONE),
+ 'neg': (0x70, OPERAND_TYPE_NONE),
+ 'and': (0x71, OPERAND_TYPE_NONE),
+ 'or': (0x72, OPERAND_TYPE_NONE),
+ 'xor': (0x73, OPERAND_TYPE_NONE),
+ 'not': (0x74, OPERAND_TYPE_NONE),
# relational
- 'eq': (0x71, OPERAND_TYPE_NONE),
- 'ne': (0x72, OPERAND_TYPE_NONE),
- 'lt': (0x73, OPERAND_TYPE_NONE),
- 'lt.u': (0x74, OPERAND_TYPE_NONE),
- 'le': (0x75, OPERAND_TYPE_NONE),
- 'le.u': (0x76, OPERAND_TYPE_NONE),
- 'gt': (0x77, OPERAND_TYPE_NONE),
- 'gt.u': (0x78, OPERAND_TYPE_NONE),
- 'ge': (0x79, OPERAND_TYPE_NONE),
- 'ge.u': (0x7a, OPERAND_TYPE_NONE),
+ 'eq': (0x75, OPERAND_TYPE_NONE),
+ 'ne': (0x76, OPERAND_TYPE_NONE),
+ 'lt': (0x77, OPERAND_TYPE_NONE),
+ 'lt.u': (0x78, OPERAND_TYPE_NONE),
+ 'le': (0x79, OPERAND_TYPE_NONE),
+ 'le.u': (0x7a, OPERAND_TYPE_NONE),
+ 'gt': (0x7b, OPERAND_TYPE_NONE),
+ 'gt.u': (0x7c, OPERAND_TYPE_NONE),
+ 'ge': (0x7d, OPERAND_TYPE_NONE),
+ 'ge.u': (0x7e, OPERAND_TYPE_NONE),
# control flow
- 'adjpc.f': (0x7b, OPERAND_TYPE_AUTO),
- 'adjpc.f.i8': (0x7b, OPERAND_TYPE_I8),
- 'adjpc.f.i16': (0x7c, OPERAND_TYPE_I16),
- 'adjpc.f.i32': (0x7d, OPERAND_TYPE_I32),
- 'adjpc.t': (0x7e, OPERAND_TYPE_AUTO),
- 'adjpc.t.i8': (0x7e, OPERAND_TYPE_I8),
- 'adjpc.t.i16': (0x7f, OPERAND_TYPE_I16),
- 'adjpc.t.i32': (0x80, OPERAND_TYPE_I32),
- 'call.w': (0x81, OPERAND_TYPE_NONE),
- 'call': (0x82, OPERAND_TYPE_AUTO),
- 'call.i8': (0x82, OPERAND_TYPE_I8),
- 'call.i16': (0x83, OPERAND_TYPE_I16),
- 'call.i32': (0x84, OPERAND_TYPE_I32),
- 'ret': (0x85, OPERAND_TYPE_NONE),
- 'trap': (0x86, OPERAND_TYPE_NONE),
+ 'adjpc.f': (0x7f, OPERAND_TYPE_AUTO),
+ 'adjpc.f.i8': (0x7f, OPERAND_TYPE_I8),
+ 'adjpc.f.i16': (0x80, OPERAND_TYPE_I16),
+ 'adjpc.f.i32': (0x81, OPERAND_TYPE_I32),
+ 'adjpc.t': (0x82, OPERAND_TYPE_AUTO),
+ 'adjpc.t.i8': (0x82, OPERAND_TYPE_I8),
+ 'adjpc.t.i16': (0x83, OPERAND_TYPE_I16),
+ 'adjpc.t.i32': (0x84, OPERAND_TYPE_I32),
+ 'call.w': (0x85, OPERAND_TYPE_NONE),
+ 'call': (0x86, OPERAND_TYPE_AUTO),
+ 'call.i8': (0x86, OPERAND_TYPE_I8),
+ 'call.i16': (0x87, OPERAND_TYPE_I16),
+ 'call.i32': (0x88, OPERAND_TYPE_I32),
+ 'ret': (0x89, OPERAND_TYPE_NONE),
+ 'trap': (0x8a, OPERAND_TYPE_NONE),
}
# for auto operands
fuzz += waste - autos[auto]
autos[auto] = waste
auto += 1
+ elif mnemonic == '.space':
+ assert len(fields) == 1
+ operand_str = fields[0]
+ assert operand_str[:1] in digit_set
+ operand_int = int(operand_str, 0)
+
+ if flist is not None:
+ flist.write(f'{pc:08x}\t\t\t\t\t{mnemonic:s} {operand_str:s}\n')
+
+ pc += operand_int
+ if fout is not None:
+ fout.write(bytes([0] * operand_int))
else:
op, operand_type = mnemonics[mnemonic]
if operand_type == OPERAND_TYPE_NONE:
main: ; stack alignment 16
imm.i32 hello_world
call print_str@
+
adjsp -0xc
imm.i128 0x0123456789abcdeffedcba9876543210
call print_hex_i128@
- imm.i128 0x0123456789abcdeffedcba9876543210
- call print_hex_i128@
adjsp 0xc
imm.i32 0xa
push
call putchar@
adjsp 4
+
+ adjsp -0xc
+ imm.i128 0
+ call print_dec_i128@
+ adjsp 0xc
+ imm.i32 0xa
+ push
+ call putchar@
+ adjsp 4
+
+ adjsp -0xc
+ imm.i128 12345678901234567890123456789
+ call print_dec_i128@
+ adjsp 0xc
+ imm.i32 0xa
+ push
+ call putchar@
+ adjsp 4
+
+ adjsp -0xc
+ imm.i128 -12345678901234567890123456789
+ call print_dec_i128@
+ adjsp 0xc
+ imm.i32 0xa
+ push
+ call putchar@
+ adjsp 4
+
+ adjsp -0xc
+ imm.f128 0
+ call print_sci_f128@
+ adjsp 0xc
+ imm.i32 0xa
+ push
+ call putchar@
+ adjsp 4
+
+ adjsp -0xc
+ imm.f128 1.234567890123456789012345678901234567e999
+ call print_sci_f128@
+ adjsp 0xc
+ imm.i32 0xa
+ push
+ call putchar@
+ adjsp 4
+
+ adjsp -0xc
+ imm.f128 -1.234567890123456789012345678901234567e-999
+ call print_sci_f128@
+ adjsp 0xc
+ imm.i32 0xa
+ push
+ call putchar@
+ adjsp 4
+
+ adjsp -0xc
+ imm.f128 6.475175119438025110924438958227646552e-4966
+ call print_sci_f128@
+ adjsp 0xc
+ imm.i32 0xa
+ push
+ call putchar@
+ adjsp 4
+
imm.i32 0
push
call exit@
hello_world:
- .i8 'h
- .i8 'e
- .i8 'l
- .i8 'l
- .i8 'o
- .i8 ',
- .i8 0x20
- .i8 'w
- .i8 'o
- .i8 'r
- .i8 'l
- .i8 'd
- .i8 0xa
- .i8 0
+ .i8 'h
+ .i8 'e
+ .i8 'l
+ .i8 'l
+ .i8 'o
+ .i8 ',
+ .i8 0x20
+ .i8 'w
+ .i8 'o
+ .i8 'r
+ .i8 'l
+ .i8 'd
+ .i8 0xa
+ .i8 0
print_str:
setix
print_hex_i128: ; stack alignment 16
push
+
push
imm.i8 64
shr.i128
adjsp -4
call print_hex_i64@
adjsp 4
+
pop.i128
cvt.i64
+ ; fallthru
+
print_hex_i64: ; stack alignment 8
push
+
push
imm.i8 32
shr.i64
cvt.i32
call print_hex_i32@
+
pop.i64
cvt.i32
+ ; fallthru
+
print_hex_i32:
push
+
push
imm.i8 16
shr.i32
cvt.i16
call print_hex_i16@
+
pop.i32
cvt.i16
+ ; fallthru
+
print_hex_i16:
push
+
push
imm.i8 8
shr.i16
cvt.i8
call print_hex_i8@
adjsp 2
+
pop.i16
cvt.i8
+ ; fallthru
+
print_hex_i8:
push
+
push
imm.i8 4
shr.i8
call print_hex_nibble@
adjsp 3
+
pop.i8
+ ; fallthru
+
print_hex_nibble:
push
imm.i8 0xf
and
cvt.i32
+
push
- imm.i32 hex_table
+ imm.i32 print_hex_table
add
ld.i8
+
cvt.i32
push
call putchar@
adjsp 4
+
ret
-hex_table:
- .i8 '0
- .i8 '1
- .i8 '2
- .i8 '3
- .i8 '4
- .i8 '5
- .i8 '6
- .i8 '7
- .i8 '8
- .i8 '9
- .i8 'a
- .i8 'b
- .i8 'c
- .i8 'd
- .i8 'e
- .i8 'f
-
- .f128 1.234567890123456789012345678901234567e999
- .f128 -1.234567890123456789012345678901234567e-999
- .f128 6.475175119438025110924438958227646552e-4966
+print_hex_table:
+ .i8 '0
+ .i8 '1
+ .i8 '2
+ .i8 '3
+ .i8 '4
+ .i8 '5
+ .i8 '6
+ .i8 '7
+ .i8 '8
+ .i8 '9
+ .i8 'a
+ .i8 'b
+ .i8 'c
+ .i8 'd
+ .i8 'e
+ .i8 'f
+
+print_dec_i128: ; stack alignment 16
+ push
+
+ push
+ imm.i128 0
+ lt
+ adjpc.f print_dec_pos@
+
+ imm.i32 '-
+ push
+ call putchar@
+ adjsp 4
+
+ pop.i128
+ neg
+ push
+
+print_dec_pos:
+ imm.i32 print_dec_buf_end
+ setix
+
+ pop.i128
+print_dec_loop0:
+ push
+
+ push
+ imm.i128 10
+ mod.u
+ cvt.i8
+ push
+ imm.i8 '0
+ add
+ push
+ adjix -1
+ getix
+ st.r.i8
+
+ imm.i128 10
+ div.u
+ adjpc.t print_dec_loop0@
+
+print_dec_loop1:
+ getix
+ ld.i8
+ cvt.i32
+ push
+ call putchar@
+ adjsp 4
+
+ adjix 1
+ getix
+ push
+ imm.i32 print_dec_buf_end
+ lt.u
+ adjpc.t print_dec_loop1@
+
+ ret
+
+ .space 39 ; 1 << 127 == 170141183460469231731687303715884105728
+print_dec_buf_end:
+
+print_sci_f128:
+ push
+
+ push
+ imm.f128 0
+ lt
+ adjpc.f print_sci_pos@
+
+ imm.i32 '-
+ push
+ call putchar@
+ adjsp 4
+
+ pop.f128
+ neg
+ push
+
+print_sci_pos:
+ ; ix points to table of exponents
+ ; when dividing it down:
+ ; entry is struct with threshold value (> 1) then scaling value (< 1)
+ ; when multiplying it up:
+ ; entry is struct with scaling value (> 1) then threshold value (< 1)
+ imm.i32 print_sci_table
+ setix
+
+ ; if number is >= 1, exponent is positive and we'll divide it down
+ ; if number is < 1, exponent is negative and we'll multiply it up
+ pop.f128
+ push
+
+ push
+ imm.f128 1
+ lt
+ adjpc.t print_sci_multiply@
+
+ ; dividing it down case
+
+ ; iy is shift register for exponent bits
+ imm.i32 0
+ setiy
+
+print_sci_loop0:
+ ; calculate next exponent bit
+ pop.f128
+ push
+
+ push
+ getix
+ ld.f128
+ ge
+ push
+
+ ; shift exponent bit into iy
+ cvt.i32
+ push
+ getiy
+ push
+ imm.i8 1
+ shl.i32
+ or
+ setiy
+ adjsp 3
+
+ ; if exponent bit is 1, divide
+ pop.i8
+ adjpc.f print_sci_no_div@
+
+ offix 0x10
+ ld.f128
+ mul
+ push
+
+print_sci_no_div:
+ adjix 0x20
+ getix
+ push
+ imm.i32 print_sci_table_end
+ lt.u
+ adjpc.t print_sci_loop0@
+
+ imm.f128 1e36 ; factor to shift left by 36 decimal places
+ adjpc print_sci_normalized@
+
+print_sci_multiply:
+ ; multiplying it up case
+
+ ; iy is shift register for exponent bits
+ ; we will build negative exponent directly, starting with all ones
+ imm.i32 -1
+ setiy
+
+print_sci_loop1:
+ ; calculate next exponent bit
+ pop.f128
+ push
+
+ push
+ offix 0x10
+ ld.f128
+ ge
+ push
+
+ ; shift exponent bit into iy
+ cvt.i32
+ push
+ getiy
+ push
+ imm.i8 1
+ shl.i32
+ or
+ setiy
+ adjsp 3
+
+ ; if exponent bit is 0, multiply
+ pop.i8
+ adjpc.t print_sci_no_mul@
+
+ getix
+ ld.f128
+ mul
+ push
+
+print_sci_no_mul:
+ adjix 0x20
+ getix
+ push
+ imm.i32 print_sci_table_end
+ lt.u
+ adjpc.t print_sci_loop1@
+
+ ; at this point the number is still < 1, do final multiply by 10
+ ; we used "not exponent" rather than "neg exponent" for extra -1
+ imm.f128 1e37 ; 10 * factor to shift left by 36 decimal places
+
+print_sci_normalized:
+ ; convert mantissa to 37 digit integer with 36 decimal places
+ mul
+ push
+ imm.f128 .5
+ add
+ cvt.i128
+ push
+
+ ; if mantissa is zero, zero out exponent as well
+ adjpc.t print_sci_not_zero@
+
+ imm.i32 0
+ setiy
+ adjpc print_sci_no_overflow@
+
+print_sci_not_zero:
+ ; check for 38-digit integer (rounding overflow)
+ push
+ imm.i128 10000000000000000000000000000000000000
+ ge.u
+ adjpc.f print_sci_no_overflow@
+
+ ; move along one digit position and bump exponent
+ ; note: no rounding is needed, as low order digit must be 0
+ imm.i128 10
+ div.u
+ push
+ adjiy 1
+
+print_sci_no_overflow:
+ ; render all 37 digits backwards into buffer
+ imm.i32 print_sci_buf_end
+ setix
+
+print_sci_loop2:
+ pop.i128
+ push
+
+ push
+ imm.i128 10
+ mod.u
+ cvt.i8
+ push
+ imm.i8 '0
+ add
+ push
+ adjix -1
+ getix
+ st.r.i8
+
+ imm.i128 10
+ div.u
+ push
+
+ getix
+ push
+ imm.i32 print_sci_buf
+ gt.u
+ adjpc.t print_sci_loop2@
+
+ pop.i128 ; should be 0, discard
+
+ ; print first digit
+ getix
+ ld.i8
+ cvt.i32
+
+ push
+ call putchar@
+ adjsp 4
+
+ adjix 1
+
+ ; print decimal point
+ imm.i32 '.
+ push
+ call putchar@
+ adjsp 4
+
+ ; print remaining digits
+print_sci_loop3:
+ getix
+ ld.i8
+ cvt.i32
+ push
+ call putchar@
+ adjsp 4
+
+ adjix 1
+ getix
+ push
+ imm.i32 print_sci_buf_end
+ lt.u
+ adjpc.t print_sci_loop3@
+
+ ; print exponent part
+ imm.i32 'e
+ push
+ call putchar@
+ adjsp 4
+
+ getiy
+ cvt.i128
+ adjpc print_dec_i128@
+
+print_sci_buf:
+ .space 37
+print_sci_buf_end:
+
+ .align 0x10
+print_sci_table:
+ .f128 1e4096
+ .f128 1e-4096
+ .f128 1e2048
+ .f128 1e-2048
+ .f128 1e1024
+ .f128 1e-1024
+ .f128 1e512
+ .f128 1e-512
+ .f128 1e256
+ .f128 1e-256
+ .f128 1e128
+ .f128 1e-128
+ .f128 1e64
+ .f128 1e-64
+ .f128 1e32
+ .f128 1e-32
+ .f128 1e16
+ .f128 1e-16
+ .f128 1e8
+ .f128 1e-8
+ .f128 1e4
+ .f128 1e-4
+ .f128 1e2
+ .f128 1e-2
+ .f128 1e1
+ .f128 1e-1
+print_sci_table_end: