Merge branch 'master' of ssh://git.sideros.org:/git/sideros
This commit is contained in:
commit
11f6bc2b04
4 changed files with 484 additions and 273 deletions
|
|
@ -39,6 +39,8 @@ pub const FunctionScope = enum {
|
||||||
const Parser = @This();
|
const Parser = @This();
|
||||||
|
|
||||||
pub const Error = error{
|
pub const Error = error{
|
||||||
|
OutOfMemory,
|
||||||
|
Overflow,
|
||||||
invalid_instruction,
|
invalid_instruction,
|
||||||
invalid_magic,
|
invalid_magic,
|
||||||
invalid_version,
|
invalid_version,
|
||||||
|
|
@ -53,6 +55,8 @@ pub const Error = error{
|
||||||
invalid_globaltype,
|
invalid_globaltype,
|
||||||
invalid_importdesc,
|
invalid_importdesc,
|
||||||
invalid_exportdesc,
|
invalid_exportdesc,
|
||||||
|
double_else,
|
||||||
|
unresolved_branch,
|
||||||
unterminated_wasm,
|
unterminated_wasm,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -61,8 +65,8 @@ fn warn(self: Parser, s: []const u8) void {
|
||||||
std.debug.print("[WARN]: Parsing of {s} unimplemented at byte index {d}\n", .{ s, self.byte_idx });
|
std.debug.print("[WARN]: Parsing of {s} unimplemented at byte index {d}\n", .{ s, self.byte_idx });
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove peek
|
// TODO: remove peek?
|
||||||
fn peek(self: Parser) ?u8 {
|
pub fn peek(self: Parser) ?u8 {
|
||||||
return if (self.byte_idx < self.bytes.len) self.bytes[self.byte_idx] else null;
|
return if (self.byte_idx < self.bytes.len) self.bytes[self.byte_idx] else null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,6 +96,10 @@ pub fn readI64(self: *Parser) !i64 {
|
||||||
return std.leb.readIleb128(i64, self);
|
return std.leb.readIleb128(i64, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn readI33(self: *Parser) !i33 {
|
||||||
|
return std.leb.readIleb128(i33, self);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn readF32(self: *Parser) !f32 {
|
pub fn readF32(self: *Parser) !f32 {
|
||||||
const bytes = try self.read(@sizeOf(f32));
|
const bytes = try self.read(@sizeOf(f32));
|
||||||
return std.mem.bytesAsValue(f32, bytes).*;
|
return std.mem.bytesAsValue(f32, bytes).*;
|
||||||
|
|
@ -140,7 +148,7 @@ fn parseVector(self: *Parser, parse_fn: anytype) ![]VectorFnResult(parse_fn) {
|
||||||
fn parseNumtype(self: *Parser) !std.wasm.Valtype {
|
fn parseNumtype(self: *Parser) !std.wasm.Valtype {
|
||||||
return switch (try self.readByte()) {
|
return switch (try self.readByte()) {
|
||||||
0x7F => .i32,
|
0x7F => .i32,
|
||||||
0x7E => .i32,
|
0x7E => .i64,
|
||||||
0x7D => .f32,
|
0x7D => .f32,
|
||||||
0x7C => .f64,
|
0x7C => .f64,
|
||||||
else => Error.invalid_numtype,
|
else => Error.invalid_numtype,
|
||||||
|
|
@ -154,7 +162,7 @@ fn parseVectype(self: *Parser) !std.wasm.Valtype {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseReftype(self: *Parser) !std.wasm.RefType {
|
pub fn parseReftype(self: *Parser) !std.wasm.RefType {
|
||||||
return switch (try self.readByte()) {
|
return switch (try self.readByte()) {
|
||||||
0x70 => .funcref,
|
0x70 => .funcref,
|
||||||
0x6F => .externref,
|
0x6F => .externref,
|
||||||
|
|
@ -462,11 +470,13 @@ fn parseCode(self: *Parser) !Func {
|
||||||
local_count += l.n;
|
local_count += l.n;
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = try IR.parse(self);
|
const ir = try IR.parse(self);
|
||||||
|
const stdout = std.io.getStdOut().writer();
|
||||||
|
try ir.print(stdout);
|
||||||
|
|
||||||
const func = Func{
|
const func = Func{
|
||||||
.locals = try self.allocator.alloc(Valtype, local_count),
|
.locals = try self.allocator.alloc(Valtype, local_count),
|
||||||
.code = try self.read(end_idx - self.byte_idx),
|
.code = &.{},
|
||||||
};
|
};
|
||||||
|
|
||||||
var li: usize = 0;
|
var li: usize = 0;
|
||||||
|
|
|
||||||
148
src/mods/ir.zig
148
src/mods/ir.zig
|
|
@ -46,6 +46,16 @@ indices: []Index,
|
||||||
// TODO: this could be a byte array and v128.const and i8x16.shuffle could live here too
|
// TODO: this could be a byte array and v128.const and i8x16.shuffle could live here too
|
||||||
select_valtypes: []Parser.Valtype,
|
select_valtypes: []Parser.Valtype,
|
||||||
|
|
||||||
|
pub fn print(self: IR, writer: anytype) !void {
|
||||||
|
for (self.opcodes, 0..) |op, i| {
|
||||||
|
try writer.print("{x:3} {s}", .{ i, @tagName(op) });
|
||||||
|
if (op == .br or op == .br_if) {
|
||||||
|
try writer.print(" {x:3}", .{self.indices[i].u32});
|
||||||
|
}
|
||||||
|
_ = try writer.write("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Opcodes.
|
/// Opcodes.
|
||||||
/// This is a mix of wasm opcodes mixed with a few of our own.
|
/// This is a mix of wasm opcodes mixed with a few of our own.
|
||||||
/// Mainly for `0xFC` opcodes we use `0xD3` to `0xE4`.
|
/// Mainly for `0xFC` opcodes we use `0xD3` to `0xE4`.
|
||||||
|
|
@ -591,17 +601,39 @@ const IRParserState = struct {
|
||||||
parser: *Parser,
|
parser: *Parser,
|
||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
|
|
||||||
|
branches: std.AutoHashMapUnmanaged(u32, u32),
|
||||||
|
|
||||||
opcodes: std.ArrayListUnmanaged(Opcode),
|
opcodes: std.ArrayListUnmanaged(Opcode),
|
||||||
indices: std.ArrayListUnmanaged(Index),
|
indices: std.ArrayListUnmanaged(Index),
|
||||||
|
|
||||||
fn parseExpression(self: *IRParserState) !void {
|
fn parseFunction(self: *IRParserState) !void {
|
||||||
|
while (true) {
|
||||||
|
const op = self.parser.peek() orelse return Parser.Error.unterminated_wasm;
|
||||||
|
if (op == 0x0B) {
|
||||||
|
_ = try self.parser.readByte();
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
try self.parseExpression();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parseExpression(self: *IRParserState) Parser.Error!void {
|
||||||
const b = try self.parser.readByte();
|
const b = try self.parser.readByte();
|
||||||
try switch (b) {
|
try switch (b) {
|
||||||
0x00...0x01 => {}, // TODO
|
0x00 => {}, // TODO
|
||||||
0x02...0x04 => {}, // TODO
|
0x01 => {},
|
||||||
0x0C...0x11 => {}, // TODO
|
0x02...0x03 => self.parseBlock(b),
|
||||||
0xD0...0xD2 => {}, // TODO
|
0x04 => self.parseIf(),
|
||||||
0x1A...0x1C => {}, // TODO
|
0x0C...0x0D => self.parseBranch(b),
|
||||||
|
0x0E => @panic("UNIMPLEMENTED"),
|
||||||
|
0x0F => self.push(@enumFromInt(b), .{ .u64 = 0 }),
|
||||||
|
0x10 => self.push(@enumFromInt(b), .{ .u32 = try self.parser.readU32() }),
|
||||||
|
0x11 => @panic("UNIMPLEMENTED"),
|
||||||
|
0xD0 => self.push(@enumFromInt(b), .{ .reftype = try self.parser.parseReftype() }),
|
||||||
|
0xD1 => self.push(@enumFromInt(b), .{ .u64 = 0 }),
|
||||||
|
0xD2 => self.push(@enumFromInt(b), .{ .u32 = try self.parser.readU32() }),
|
||||||
|
0x1A...0x1C => @panic("UNIMPLEMENTED"),
|
||||||
0x20...0x24 => self.push(@enumFromInt(b), .{ .u32 = try self.parser.readU32() }),
|
0x20...0x24 => self.push(@enumFromInt(b), .{ .u32 = try self.parser.readU32() }),
|
||||||
0x25...0x26 => self.push(@enumFromInt(b), .{ .u32 = try self.parser.readU32() }),
|
0x25...0x26 => self.push(@enumFromInt(b), .{ .u32 = try self.parser.readU32() }),
|
||||||
0x28...0x3E => self.push(@enumFromInt(b), .{ .memarg = try self.parseMemarg() }),
|
0x28...0x3E => self.push(@enumFromInt(b), .{ .memarg = try self.parseMemarg() }),
|
||||||
|
|
@ -649,8 +681,8 @@ const IRParserState = struct {
|
||||||
const n = try self.parser.readU32();
|
const n = try self.parser.readU32();
|
||||||
try switch (n) {
|
try switch (n) {
|
||||||
0...7 => self.push(@enumFromInt(0xD3 + @as(u8, @intCast(n))), .{ .u64 = 0 }),
|
0...7 => self.push(@enumFromInt(0xD3 + @as(u8, @intCast(n))), .{ .u64 = 0 }),
|
||||||
8...11 => {}, // TODO
|
8...11 => @panic("UNIMPLEMENTED"),
|
||||||
12...17 => {}, // TODO
|
12...17 => @panic("UNIMPLEMENTED"),
|
||||||
else => {
|
else => {
|
||||||
std.log.err("Invalid misc instruction {d} at position {d}\n", .{ n, self.parser.byte_idx });
|
std.log.err("Invalid misc instruction {d} at position {d}\n", .{ n, self.parser.byte_idx });
|
||||||
return Parser.Error.invalid_instruction;
|
return Parser.Error.invalid_instruction;
|
||||||
|
|
@ -658,6 +690,101 @@ const IRParserState = struct {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parseBlockType(self: *IRParserState) !void {
|
||||||
|
const b = self.parser.peek() orelse return Parser.Error.unterminated_wasm;
|
||||||
|
switch (b) {
|
||||||
|
0x40 => _ = try self.parser.readByte(),
|
||||||
|
0x6F...0x70, 0x7B...0x7F => _ = try self.parser.readByte(),
|
||||||
|
else => _ = try self.parser.readI33(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parseBlock(self: *IRParserState, b: u8) !void {
|
||||||
|
// TODO: Should we do something with this?
|
||||||
|
_ = try self.parseBlockType();
|
||||||
|
const start: u32 = @intCast(self.opcodes.items.len);
|
||||||
|
while (true) {
|
||||||
|
const op = self.parser.peek() orelse return Parser.Error.unterminated_wasm;
|
||||||
|
if (op == 0x0B) {
|
||||||
|
_ = try self.parser.readByte();
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
try self.parseExpression();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const end: u32 = @intCast(self.opcodes.items.len);
|
||||||
|
const jump_addr: u32 = switch (b) {
|
||||||
|
0x02 => end,
|
||||||
|
0x03 => start,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
try self.fix_branches_for_block(start, end, jump_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parseIf(self: *IRParserState) !void {
|
||||||
|
// TODO: Should we do something with this?
|
||||||
|
_ = try self.parseBlockType();
|
||||||
|
|
||||||
|
try self.push(.br_if, .{ .u32 = @intCast(self.opcodes.items.len + 2) });
|
||||||
|
const start: u32 = @intCast(self.opcodes.items.len);
|
||||||
|
try self.push(.br, .{ .u32 = 0 });
|
||||||
|
|
||||||
|
var else_addr: u32 = 0;
|
||||||
|
while (true) {
|
||||||
|
const op = self.parser.peek() orelse return Parser.Error.unterminated_wasm;
|
||||||
|
|
||||||
|
if (op == 0x05) {
|
||||||
|
if (else_addr != 0) return Parser.Error.double_else;
|
||||||
|
_ = try self.parser.readByte();
|
||||||
|
else_addr = @intCast(self.opcodes.items.len);
|
||||||
|
try self.push(.br, .{ .u32 = 0 });
|
||||||
|
} else if (op == 0x0B) {
|
||||||
|
_ = try self.parser.readByte();
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
try self.parseExpression();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const end: u32 = @intCast(self.opcodes.items.len);
|
||||||
|
|
||||||
|
if (else_addr > 0) {
|
||||||
|
self.indices.items[start].u32 = else_addr + 1;
|
||||||
|
self.indices.items[else_addr].u32 = end;
|
||||||
|
} else {
|
||||||
|
self.indices.items[start].u32 = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
try self.fix_branches_for_block(start, end, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fix_branches_for_block(self: *IRParserState, start: u32, end: u32, jump_addr: u32) !void {
|
||||||
|
var todel: std.ArrayListUnmanaged(u32) = .{};
|
||||||
|
defer todel.deinit(self.allocator);
|
||||||
|
|
||||||
|
var it = self.branches.iterator();
|
||||||
|
while (it.next()) |branch| {
|
||||||
|
if (start < branch.key_ptr.* and branch.key_ptr.* < end) {
|
||||||
|
if (branch.value_ptr.* == 0) {
|
||||||
|
self.indices.items[branch.key_ptr.*].u32 = jump_addr;
|
||||||
|
try todel.append(self.allocator, branch.key_ptr.*);
|
||||||
|
} else {
|
||||||
|
branch.value_ptr.* -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (todel.items) |d| {
|
||||||
|
// TODO: Do we need to assert this is true?
|
||||||
|
_ = self.branches.remove(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parseBranch(self: *IRParserState, b: u8) !void {
|
||||||
|
const idx = try self.parser.readU32();
|
||||||
|
try self.branches.put(self.allocator, @intCast(self.opcodes.items.len), idx);
|
||||||
|
try self.push(@enumFromInt(b), .{ .u64 = 0 });
|
||||||
|
}
|
||||||
|
|
||||||
fn parseVector(self: *IRParserState) !void {
|
fn parseVector(self: *IRParserState) !void {
|
||||||
const n = try self.parser.readU32();
|
const n = try self.parser.readU32();
|
||||||
try switch (n) {
|
try switch (n) {
|
||||||
|
|
@ -682,11 +809,12 @@ pub fn parse(parser: *Parser) !IR {
|
||||||
var state = IRParserState{
|
var state = IRParserState{
|
||||||
.opcodes = .{},
|
.opcodes = .{},
|
||||||
.indices = .{},
|
.indices = .{},
|
||||||
|
.branches = .{},
|
||||||
.parser = parser,
|
.parser = parser,
|
||||||
.allocator = parser.allocator,
|
.allocator = parser.allocator,
|
||||||
};
|
};
|
||||||
std.debug.print("Parsing\n", .{});
|
try state.parseFunction();
|
||||||
try state.parseExpression();
|
if (state.branches.count() != 0) return Parser.Error.unresolved_branch;
|
||||||
return .{
|
return .{
|
||||||
.opcodes = try state.opcodes.toOwnedSlice(state.allocator),
|
.opcodes = try state.opcodes.toOwnedSlice(state.allocator),
|
||||||
.indices = try state.indices.toOwnedSlice(state.allocator),
|
.indices = try state.indices.toOwnedSlice(state.allocator),
|
||||||
|
|
|
||||||
|
|
@ -6,3 +6,42 @@ pub const IR = @import("ir.zig");
|
||||||
|
|
||||||
pub const GlobalRuntime = Wasm.GlobalRuntime;
|
pub const GlobalRuntime = Wasm.GlobalRuntime;
|
||||||
pub const Runtime = VM.Runtime;
|
pub const Runtime = VM.Runtime;
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
test "Fibonacci" {
|
||||||
|
// var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
|
// const allocator = gpa.allocator();
|
||||||
|
const allocator = std.testing.allocator;
|
||||||
|
var global_runtime = GlobalRuntime.init(allocator);
|
||||||
|
defer global_runtime.deinit();
|
||||||
|
|
||||||
|
const file = try std.fs.cwd().openFile("assets/core.wasm", .{});
|
||||||
|
const all = try file.readToEndAlloc(allocator, 1_000_000); // 1 MB
|
||||||
|
var parser = Parser{
|
||||||
|
.bytes = all,
|
||||||
|
.byte_idx = 0,
|
||||||
|
.allocator = allocator,
|
||||||
|
};
|
||||||
|
const module = parser.parseModule() catch |err| {
|
||||||
|
std.debug.print("[ERROR]: error at byte {x}(0x{x})\n", .{ parser.byte_idx, parser.bytes[parser.byte_idx] });
|
||||||
|
return err;
|
||||||
|
};
|
||||||
|
var runtime = try Runtime.init(allocator, module, &global_runtime);
|
||||||
|
defer runtime.deinit(allocator);
|
||||||
|
|
||||||
|
var parameters = [_]usize{17};
|
||||||
|
try runtime.callExternal(allocator, "preinit", ¶meters);
|
||||||
|
const result = runtime.stack.pop().?;
|
||||||
|
try std.testing.expect(result.i64 == 1597);
|
||||||
|
|
||||||
|
var parameters2 = [_]usize{1};
|
||||||
|
try runtime.callExternal(allocator, "preinit", ¶meters2);
|
||||||
|
const result2 = runtime.stack.pop().?;
|
||||||
|
try std.testing.expect(result2.i64 == 1);
|
||||||
|
|
||||||
|
var parameters3 = [_]usize{5};
|
||||||
|
try runtime.callExternal(allocator, "preinit", ¶meters3);
|
||||||
|
const result3 = runtime.stack.pop().?;
|
||||||
|
try std.testing.expect(result3.i64 == 5);
|
||||||
|
}
|
||||||
|
|
|
||||||
550
src/mods/vm.zig
550
src/mods/vm.zig
|
|
@ -162,7 +162,7 @@ pub const Runtime = struct {
|
||||||
loop: while (true) {
|
loop: while (true) {
|
||||||
const byte: u8 = frame.code[frame.program_counter];
|
const byte: u8 = frame.code[frame.program_counter];
|
||||||
frame.program_counter += 1;
|
frame.program_counter += 1;
|
||||||
std.debug.print("b: {x}\n", .{byte});
|
// std.debug.print("b: 0x{x} pc: 0x{x}\n", .{ byte, frame.program_counter-1 });
|
||||||
switch (byte) {
|
switch (byte) {
|
||||||
0x02 => {
|
0x02 => {
|
||||||
var depth: usize = 1;
|
var depth: usize = 1;
|
||||||
|
|
@ -170,8 +170,9 @@ pub const Runtime = struct {
|
||||||
while (depth > 0) {
|
while (depth > 0) {
|
||||||
const opcode = frame.code[pc];
|
const opcode = frame.code[pc];
|
||||||
const operand = frame.code[pc + 1];
|
const operand = frame.code[pc + 1];
|
||||||
if (opcode == 0x02 and operand == 0x40) {
|
if ((opcode == 0x02 and operand == 0x40) or (opcode == 0x03 and operand == 0x40) or (opcode == 0x04 and operand == 0x40)) {
|
||||||
depth += 1;
|
depth += 1;
|
||||||
|
pc += 1;
|
||||||
} else if (opcode == 0x0B) {
|
} else if (opcode == 0x0B) {
|
||||||
depth -= 1;
|
depth -= 1;
|
||||||
}
|
}
|
||||||
|
|
@ -181,21 +182,28 @@ pub const Runtime = struct {
|
||||||
frame.program_counter += 1;
|
frame.program_counter += 1;
|
||||||
},
|
},
|
||||||
0x03 => {
|
0x03 => {
|
||||||
try self.labels.append(frame.program_counter);
|
try self.labels.append(frame.program_counter - 1);
|
||||||
frame.program_counter += 1;
|
frame.program_counter += 1;
|
||||||
//const a = frame.code[frame.program_counter];
|
|
||||||
for_loop = true;
|
for_loop = true;
|
||||||
},
|
},
|
||||||
0x0d => {
|
0x0c => {
|
||||||
const label = leb128Decode(u32, frame.code[frame.program_counter..]);
|
const label = leb128Decode(u32, frame.code[frame.program_counter..]);
|
||||||
frame.program_counter += label.len;
|
|
||||||
var address = @as(usize, 0);
|
var address = @as(usize, 0);
|
||||||
for (0..(label.val)) |_| {
|
for (0..(label.val + (if (label.val == 0) @as(u32, 1) else @as(u32, 0)))) |_| {
|
||||||
address = self.labels.pop().?;
|
address = self.labels.pop().?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.stack.pop().?.i32 != 0) {
|
|
||||||
frame.program_counter = address;
|
frame.program_counter = address;
|
||||||
|
},
|
||||||
|
0x0d => {
|
||||||
|
if (self.stack.pop().?.i32 != 0) {
|
||||||
|
const label = leb128Decode(u32, frame.code[frame.program_counter..]);
|
||||||
|
var address = @as(usize, 0);
|
||||||
|
for (0..(label.val + (if (label.val == 0) @as(u32, 1) else @as(u32, 0)))) |_| {
|
||||||
|
address = self.labels.pop().?;
|
||||||
|
}
|
||||||
|
frame.program_counter = address;
|
||||||
|
} else {
|
||||||
|
frame.program_counter += 1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -215,8 +223,9 @@ pub const Runtime = struct {
|
||||||
const integer = leb128Decode(u32, frame.code[frame.program_counter..]);
|
const integer = leb128Decode(u32, frame.code[frame.program_counter..]);
|
||||||
|
|
||||||
frame.program_counter += integer.len;
|
frame.program_counter += integer.len;
|
||||||
frame.locals[integer.val] = self.stack.pop().?;
|
const a = self.stack.pop().?;
|
||||||
try self.stack.append(Value{ .i32 = @intCast(integer.val) });
|
frame.locals[integer.val] = a;
|
||||||
|
try self.stack.append(a);
|
||||||
},
|
},
|
||||||
0x28 => {
|
0x28 => {
|
||||||
const address = leb128Decode(u32, frame.code[frame.program_counter..]);
|
const address = leb128Decode(u32, frame.code[frame.program_counter..]);
|
||||||
|
|
@ -284,33 +293,45 @@ pub const Runtime = struct {
|
||||||
0x47 => {
|
0x47 => {
|
||||||
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i32 != self.stack.pop().?.i32))) });
|
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i32 != self.stack.pop().?.i32))) });
|
||||||
},
|
},
|
||||||
0x48 => {
|
// 0x48 => {
|
||||||
const a = self.stack.pop().?.i32;
|
// const a = self.stack.pop().?.i32;
|
||||||
const b = self.stack.pop().?.i32;
|
// const b = self.stack.pop().?.i32;
|
||||||
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(b < a))) });
|
// try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(b < a))) });
|
||||||
},
|
// },
|
||||||
0x49 => {
|
0x49 => {
|
||||||
const a = self.stack.pop().?.i32;
|
const a = self.stack.pop().?.i32;
|
||||||
const b = self.stack.pop().?.i32;
|
const b = self.stack.pop().?.i32;
|
||||||
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(b < a))) });
|
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(b < a))) });
|
||||||
},
|
},
|
||||||
0x4a => {
|
// 0x4b => {
|
||||||
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i32 > self.stack.pop().?.i32))) });
|
// const b = self.stack.pop().?.i32;
|
||||||
},
|
// const a = self.stack.pop().?.i32;
|
||||||
0x4b => {
|
// try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(a > b))) });
|
||||||
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(@as(u32, @bitCast(self.stack.pop().?.i32)) > @as(u32, @bitCast(self.stack.pop().?.i32))))) });
|
// },
|
||||||
},
|
// 0x4d => {
|
||||||
0x4c => {
|
// const b = self.stack.pop().?.i32;
|
||||||
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i32 <= self.stack.pop().?.i32))) });
|
// const a = self.stack.pop().?.i32;
|
||||||
},
|
// try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(b <= a))) });
|
||||||
0x4d => {
|
// },
|
||||||
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(@as(u32, @bitCast(self.stack.pop().?.i32)) <= @as(u32, @bitCast(self.stack.pop().?.i32))))) });
|
// 0x4a => {
|
||||||
},
|
// try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i32 > self.stack.pop().?.i32))) });
|
||||||
0x4e => {
|
// },
|
||||||
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i32 >= self.stack.pop().?.i32))) });
|
// 0x4b => {
|
||||||
},
|
// try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(@as(u32, @bitCast(self.stack.pop().?.i32)) > @as(u32, @bitCast(self.stack.pop().?.i32))))) });
|
||||||
|
// },
|
||||||
|
// 0x4c => {
|
||||||
|
// try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i32 <= self.stack.pop().?.i32))) });
|
||||||
|
// },
|
||||||
|
// 0x4d => {
|
||||||
|
// try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(@as(u32, @bitCast(self.stack.pop().?.i32)) <= @as(u32, @bitCast(self.stack.pop().?.i32))))) });
|
||||||
|
// },
|
||||||
|
// 0x4e => {
|
||||||
|
// try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i32 >= self.stack.pop().?.i32))) });
|
||||||
|
// },
|
||||||
0x4f => {
|
0x4f => {
|
||||||
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(@as(u32, @bitCast(self.stack.pop().?.i32)) >= @as(u32, @bitCast(self.stack.pop().?.i32))))) });
|
const a = self.stack.pop().?.i32;
|
||||||
|
const b = self.stack.pop().?.i32;
|
||||||
|
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(a >= b))) });
|
||||||
},
|
},
|
||||||
|
|
||||||
0x50 => {
|
0x50 => {
|
||||||
|
|
@ -322,247 +343,254 @@ pub const Runtime = struct {
|
||||||
0x52 => {
|
0x52 => {
|
||||||
try self.stack.append(Value{ .i64 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i64 != self.stack.pop().?.i64))) });
|
try self.stack.append(Value{ .i64 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i64 != self.stack.pop().?.i64))) });
|
||||||
},
|
},
|
||||||
0x53 => {
|
// 0x53 => {
|
||||||
try self.stack.append(Value{ .i64 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i64 < self.stack.pop().?.i64))) });
|
// try self.stack.append(Value{ .i64 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i64 < self.stack.pop().?.i64))) });
|
||||||
},
|
// },
|
||||||
0x54 => {
|
// 0x54 => {
|
||||||
try self.stack.append(Value{ .i64 = @intCast(@as(u1, @bitCast(@as(u64, @bitCast(self.stack.pop().?.i64)) < @as(u64, @bitCast(self.stack.pop().?.i64))))) });
|
// try self.stack.append(Value{ .i64 = @intCast(@as(u1, @bitCast(@as(u64, @bitCast(self.stack.pop().?.i64)) < @as(u64, @bitCast(self.stack.pop().?.i64))))) });
|
||||||
},
|
// },
|
||||||
0x55 => {
|
// 0x55 => {
|
||||||
try self.stack.append(Value{ .i64 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i64 > self.stack.pop().?.i64))) });
|
// try self.stack.append(Value{ .i64 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i64 > self.stack.pop().?.i64))) });
|
||||||
},
|
// },
|
||||||
0x56 => {
|
// 0x56 => {
|
||||||
try self.stack.append(Value{ .i64 = @intCast(@as(u1, @bitCast(@as(u64, @bitCast(self.stack.pop().?.i64)) > @as(u64, @bitCast(self.stack.pop().?.i64))))) });
|
// try self.stack.append(Value{ .i64 = @intCast(@as(u1, @bitCast(@as(u64, @bitCast(self.stack.pop().?.i64)) > @as(u64, @bitCast(self.stack.pop().?.i64))))) });
|
||||||
},
|
// },
|
||||||
0x57 => {
|
// 0x57 => {
|
||||||
try self.stack.append(Value{ .i64 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i64 <= self.stack.pop().?.i64))) });
|
// try self.stack.append(Value{ .i64 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i64 <= self.stack.pop().?.i64))) });
|
||||||
},
|
// },
|
||||||
0x58 => {
|
// 0x58 => {
|
||||||
try self.stack.append(Value{ .i64 = @intCast(@as(u1, @bitCast(@as(u64, @bitCast(self.stack.pop().?.i64)) <= @as(u64, @bitCast(self.stack.pop().?.i64))))) });
|
// try self.stack.append(Value{ .i64 = @intCast(@as(u1, @bitCast(@as(u64, @bitCast(self.stack.pop().?.i64)) <= @as(u64, @bitCast(self.stack.pop().?.i64))))) });
|
||||||
},
|
// },
|
||||||
0x59 => {
|
// 0x59 => {
|
||||||
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i64 >= self.stack.pop().?.i64))) });
|
// try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(self.stack.pop().?.i64 >= self.stack.pop().?.i64))) });
|
||||||
},
|
// },
|
||||||
0x5a => {
|
// 0x5a => {
|
||||||
try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(@as(u64, @bitCast(self.stack.pop().?.i64)) >= @as(u64, @bitCast(self.stack.pop().?.i64))))) });
|
// try self.stack.append(Value{ .i32 = @intCast(@as(u1, @bitCast(@as(u64, @bitCast(self.stack.pop().?.i64)) >= @as(u64, @bitCast(self.stack.pop().?.i64))))) });
|
||||||
},
|
// },
|
||||||
|
|
||||||
0x67 => {
|
// 0x67 => {
|
||||||
var i = @as(i32, 0);
|
// var i = @as(i32, 0);
|
||||||
const number = self.stack.pop().?.i32;
|
// const number = self.stack.pop().?.i32;
|
||||||
for (0..@sizeOf(i32)) |b| {
|
// for (0..@sizeOf(i32)) |b| {
|
||||||
if (number & (@as(i32, 0x1) << @intCast((@sizeOf(i32) - b - 1))) == 1) {
|
// if (number & (@as(i32, 0x1) << @intCast((@sizeOf(i32) - b - 1))) == 1) {
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
i += 1;
|
// i += 1;
|
||||||
}
|
// }
|
||||||
try self.stack.append(Value{ .i32 = i });
|
// try self.stack.append(Value{ .i32 = i });
|
||||||
},
|
// },
|
||||||
0x68 => {
|
// 0x68 => {
|
||||||
var i = @as(i32, 0);
|
// var i = @as(i32, 0);
|
||||||
const number = self.stack.pop().?.i32;
|
// const number = self.stack.pop().?.i32;
|
||||||
for (0..@sizeOf(i32)) |b| {
|
// for (0..@sizeOf(i32)) |b| {
|
||||||
if (number & (@as(i32, 0x1) << @intCast(b)) == 1) {
|
// if (number & (@as(i32, 0x1) << @intCast(b)) == 1) {
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
i += 1;
|
// i += 1;
|
||||||
}
|
// }
|
||||||
try self.stack.append(Value{ .i32 = i });
|
// try self.stack.append(Value{ .i32 = i });
|
||||||
},
|
// },
|
||||||
0x69 => {
|
// 0x69 => {
|
||||||
var i = @as(i32, 0);
|
// var i = @as(i32, 0);
|
||||||
const number = self.stack.pop().?.i32;
|
// const number = self.stack.pop().?.i32;
|
||||||
for (0..@sizeOf(i32)) |b| {
|
// for (0..@sizeOf(i32)) |b| {
|
||||||
if (number & (@as(i32, 0x1) << @intCast(b)) == 1) {
|
// if (number & (@as(i32, 0x1) << @intCast(b)) == 1) {
|
||||||
i += 1;
|
// i += 1;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
try self.stack.append(Value{ .i32 = i });
|
// try self.stack.append(Value{ .i32 = i });
|
||||||
},
|
// },
|
||||||
0x6a => {
|
0x6a => {
|
||||||
const a = self.stack.pop().?;
|
const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i32 = a.i32 + b.i32 });
|
try self.stack.append(.{ .i32 = a.i32 + b.i32 });
|
||||||
},
|
},
|
||||||
0x6b => {
|
// 0x6b => {
|
||||||
const a = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i32 = a.i32 - b.i32 });
|
// try self.stack.append(.{ .i32 = a.i32 - b.i32 });
|
||||||
},
|
// },
|
||||||
0x6c => {
|
// 0x6c => {
|
||||||
const a = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i32 = a.i32 * b.i32 });
|
// try self.stack.append(.{ .i32 = a.i32 * b.i32 });
|
||||||
},
|
// },
|
||||||
0x6d => {
|
// 0x6d => {
|
||||||
const a = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i32 = @divTrunc(a.i32, b.i32) });
|
// try self.stack.append(.{ .i32 = @divTrunc(a.i32, b.i32) });
|
||||||
},
|
// },
|
||||||
0x6e => {
|
// 0x6e => {
|
||||||
const a = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i32 = @as(i32, @bitCast(@as(u32, @bitCast(a.i32)) / @as(u32, @bitCast(b.i32)))) });
|
// try self.stack.append(.{ .i32 = @as(i32, @bitCast(@as(u32, @bitCast(a.i32)) / @as(u32, @bitCast(b.i32)))) });
|
||||||
},
|
// },
|
||||||
0x6f => {
|
// 0x6f => {
|
||||||
const a = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i32 = @rem(a.i32, b.i32) });
|
// try self.stack.append(.{ .i32 = @rem(a.i32, b.i32) });
|
||||||
},
|
// },
|
||||||
0x70 => {
|
// 0x70 => {
|
||||||
const a = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i32 = @as(i32, @bitCast(@as(u32, @bitCast(a.i32)) % @as(u32, @bitCast(b.i32)))) });
|
// try self.stack.append(.{ .i32 = @as(i32, @bitCast(@as(u32, @bitCast(a.i32)) % @as(u32, @bitCast(b.i32)))) });
|
||||||
},
|
// },
|
||||||
0x71 => {
|
0x71 => {
|
||||||
const a = self.stack.pop().?;
|
const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i32 = a.i32 & b.i32 });
|
try self.stack.append(.{ .i32 = a.i32 & b.i32 });
|
||||||
},
|
},
|
||||||
0x72 => {
|
// 0x72 => {
|
||||||
const a = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i32 = a.i32 | b.i32 });
|
// try self.stack.append(.{ .i32 = a.i32 | b.i32 });
|
||||||
},
|
// },
|
||||||
0x73 => {
|
// 0x73 => {
|
||||||
const a = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i32 = a.i32 ^ b.i32 });
|
// try self.stack.append(.{ .i32 = a.i32 ^ b.i32 });
|
||||||
},
|
// },
|
||||||
0x74 => {
|
// 0x74 => {
|
||||||
const a = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i32 = a.i32 << @intCast(b.i32) });
|
// try self.stack.append(.{ .i32 = a.i32 << @intCast(b.i32) });
|
||||||
},
|
// },
|
||||||
0x75 => {
|
// 0x75 => {
|
||||||
const a = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i32 = a.i32 >> @intCast(b.i32) });
|
// try self.stack.append(.{ .i32 = a.i32 >> @intCast(b.i32) });
|
||||||
},
|
// },
|
||||||
0x76 => {
|
// 0x76 => {
|
||||||
const a = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i32 = @as(i32, @bitCast(@as(u32, @bitCast(a.i32)) >> @intCast(@as(u32, @bitCast(b.i32))))) });
|
// try self.stack.append(.{ .i32 = @as(i32, @bitCast(@as(u32, @bitCast(a.i32)) >> @intCast(@as(u32, @bitCast(b.i32))))) });
|
||||||
},
|
// },
|
||||||
0x77 => {
|
// 0x77 => {
|
||||||
const a = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i32 = (a.i32 << @intCast(@as(u32, @bitCast(b.i32)))) | (a.i32 >> @intCast((@sizeOf(u32) * 8 - b.i32))) });
|
// try self.stack.append(.{ .i32 = (a.i32 << @intCast(@as(u32, @bitCast(b.i32)))) | (a.i32 >> @intCast((@sizeOf(u32) * 8 - b.i32))) });
|
||||||
},
|
// },
|
||||||
0x78 => {
|
// 0x78 => {
|
||||||
const a = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i32 = (a.i32 >> @intCast(@as(u32, @bitCast(b.i32)))) | (a.i32 << @intCast((@sizeOf(u32) * 8 - b.i32))) });
|
// try self.stack.append(.{ .i32 = (a.i32 >> @intCast(@as(u32, @bitCast(b.i32)))) | (a.i32 << @intCast((@sizeOf(u32) * 8 - b.i32))) });
|
||||||
},
|
// },
|
||||||
|
|
||||||
0x79 => {
|
// 0x79 => {
|
||||||
var i = @as(i64, 0);
|
// var i = @as(i64, 0);
|
||||||
const number = self.stack.pop().?.i64;
|
// const number = self.stack.pop().?.i64;
|
||||||
for (0..@sizeOf(i64)) |b| {
|
// for (0..@sizeOf(i64)) |b| {
|
||||||
if (number & (@as(i64, 0x1) << @intCast((@sizeOf(i64) - b - 1))) == 1) {
|
// if (number & (@as(i64, 0x1) << @intCast((@sizeOf(i64) - b - 1))) == 1) {
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
i += 1;
|
// i += 1;
|
||||||
}
|
// }
|
||||||
try self.stack.append(Value{ .i64 = i });
|
// try self.stack.append(Value{ .i64 = i });
|
||||||
},
|
// },
|
||||||
0x7a => {
|
// 0x7a => {
|
||||||
var i = @as(i64, 0);
|
// var i = @as(i64, 0);
|
||||||
const number = self.stack.pop().?.i64;
|
// const number = self.stack.pop().?.i64;
|
||||||
for (0..@sizeOf(i64)) |b| {
|
// for (0..@sizeOf(i64)) |b| {
|
||||||
if (number & (@as(i64, 0x1) << @intCast(b)) == 1) {
|
// if (number & (@as(i64, 0x1) << @intCast(b)) == 1) {
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
i += 1;
|
// i += 1;
|
||||||
}
|
// }
|
||||||
try self.stack.append(Value{ .i64 = i });
|
// try self.stack.append(Value{ .i64 = i });
|
||||||
},
|
// },
|
||||||
0x7b => {
|
// 0x7b => {
|
||||||
var i = @as(i64, 0);
|
// var i = @as(i64, 0);
|
||||||
const number = self.stack.pop().?.i64;
|
// const number = self.stack.pop().?.i64;
|
||||||
for (0..@sizeOf(i64)) |b| {
|
// for (0..@sizeOf(i64)) |b| {
|
||||||
if (number & (@as(i64, 0x1) << @intCast(b)) == 1) {
|
// if (number & (@as(i64, 0x1) << @intCast(b)) == 1) {
|
||||||
i += 1;
|
// i += 1;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
try self.stack.append(Value{ .i64 = i });
|
// try self.stack.append(Value{ .i64 = i });
|
||||||
},
|
// },
|
||||||
0x7c => {
|
0x7c => {
|
||||||
const a = self.stack.pop().?;
|
const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i64 = a.i64 + b.i64 });
|
try self.stack.append(.{ .i64 = a.i64 + b.i64 });
|
||||||
},
|
},
|
||||||
0x7d => {
|
// 0x7d => {
|
||||||
const a = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i64 = a.i64 - b.i64 });
|
// try self.stack.append(.{ .i64 = a.i64 - b.i64 });
|
||||||
},
|
// },
|
||||||
0x7e => {
|
// 0x7e => {
|
||||||
const a = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i64 = a.i64 * b.i64 });
|
// try self.stack.append(.{ .i64 = a.i64 * b.i64 });
|
||||||
},
|
// },
|
||||||
0x7f => {
|
// 0x7f => {
|
||||||
const a = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i64 = @divTrunc(a.i64, b.i64) });
|
// try self.stack.append(.{ .i64 = @divTrunc(a.i64, b.i64) });
|
||||||
},
|
// },
|
||||||
0x80 => {
|
// 0x80 => {
|
||||||
const a = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i64 = @as(i64, @bitCast(@as(u64, @bitCast(a.i64)) / @as(u64, @bitCast(b.i64)))) });
|
// try self.stack.append(.{ .i64 = @as(i64, @bitCast(@as(u64, @bitCast(a.i64)) / @as(u64, @bitCast(b.i64)))) });
|
||||||
},
|
// },
|
||||||
0x81 => {
|
// 0x81 => {
|
||||||
const a = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i64 = @rem(a.i64, b.i64) });
|
// try self.stack.append(.{ .i64 = @rem(a.i64, b.i64) });
|
||||||
},
|
// },
|
||||||
0x82 => {
|
// 0x82 => {
|
||||||
const a = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i64 = @as(i64, @bitCast(@as(u64, @bitCast(a.i64)) % @as(u64, @bitCast(b.i64)))) });
|
// try self.stack.append(.{ .i64 = @as(i64, @bitCast(@as(u64, @bitCast(a.i64)) % @as(u64, @bitCast(b.i64)))) });
|
||||||
},
|
// },
|
||||||
0x83 => {
|
// 0x83 => {
|
||||||
const a = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i64 = a.i64 & b.i64 });
|
// try self.stack.append(.{ .i64 = a.i64 & b.i64 });
|
||||||
},
|
// },
|
||||||
0x84 => {
|
// 0x84 => {
|
||||||
const a = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i64 = a.i64 | b.i64 });
|
// try self.stack.append(.{ .i64 = a.i64 | b.i64 });
|
||||||
},
|
// },
|
||||||
0x85 => {
|
// 0x85 => {
|
||||||
const a = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i64 = a.i64 ^ b.i64 });
|
// try self.stack.append(.{ .i64 = a.i64 ^ b.i64 });
|
||||||
},
|
// },
|
||||||
0x86 => {
|
// 0x86 => {
|
||||||
const a = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i64 = a.i64 << @intCast(b.i64) });
|
// try self.stack.append(.{ .i64 = a.i64 << @intCast(b.i64) });
|
||||||
},
|
// },
|
||||||
0x87 => {
|
// 0x87 => {
|
||||||
const a = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i64 = a.i64 >> @intCast(b.i64) });
|
// try self.stack.append(.{ .i64 = a.i64 >> @intCast(b.i64) });
|
||||||
},
|
// },
|
||||||
0x88 => {
|
// 0x88 => {
|
||||||
const a = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i64 = @as(i64, @bitCast(@as(u64, @bitCast(a.i64)) >> @intCast(@as(u64, @bitCast(b.i64))))) });
|
// try self.stack.append(.{ .i64 = @as(i64, @bitCast(@as(u64, @bitCast(a.i64)) >> @intCast(@as(u64, @bitCast(b.i64))))) });
|
||||||
},
|
// },
|
||||||
0x89 => {
|
// 0x89 => {
|
||||||
const a = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i64 = (a.i64 << @intCast(@as(u64, @bitCast(b.i64)))) | (a.i64 >> @intCast((@sizeOf(u64) * 8 - b.i64))) });
|
// try self.stack.append(.{ .i64 = (a.i64 << @intCast(@as(u64, @bitCast(b.i64)))) | (a.i64 >> @intCast((@sizeOf(u64) * 8 - b.i64))) });
|
||||||
},
|
// },
|
||||||
0x8a => {
|
// 0x8a => {
|
||||||
const a = self.stack.pop().?;
|
// const a = self.stack.pop().?;
|
||||||
const b = self.stack.pop().?;
|
// const b = self.stack.pop().?;
|
||||||
try self.stack.append(.{ .i64 = (a.i64 >> @intCast(@as(u64, @bitCast(b.i64)))) | (a.i64 << @intCast((@sizeOf(u64) * 8 - b.i64))) });
|
// try self.stack.append(.{ .i64 = (a.i64 >> @intCast(@as(u64, @bitCast(b.i64)))) | (a.i64 << @intCast((@sizeOf(u64) * 8 - b.i64))) });
|
||||||
|
// },
|
||||||
|
|
||||||
|
0xad => {
|
||||||
|
try self.stack.append(.{ .i64 = self.stack.pop().?.i32 });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
0x0f => {
|
||||||
|
break :loop;
|
||||||
|
},
|
||||||
0x10 => {
|
0x10 => {
|
||||||
const integer = leb128Decode(u32, frame.code[frame.program_counter..]);
|
const integer = leb128Decode(u32, frame.code[frame.program_counter..]);
|
||||||
frame.program_counter += integer.len;
|
frame.program_counter += integer.len;
|
||||||
|
|
@ -570,13 +598,15 @@ pub const Runtime = struct {
|
||||||
self.call(allocator, integer.val, &[_]usize{}) catch {};
|
self.call(allocator, integer.val, &[_]usize{}) catch {};
|
||||||
},
|
},
|
||||||
0xb => {
|
0xb => {
|
||||||
|
_ = self.labels.pop();
|
||||||
if (for_loop) {
|
if (for_loop) {
|
||||||
frame.program_counter += 1;
|
for_loop = false;
|
||||||
} else {
|
|
||||||
break :loop;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => std.debug.print("instruction {} not implemented\n", .{byte}),
|
else => std.log.err("instruction {} not implemented\n", .{byte}),
|
||||||
|
}
|
||||||
|
if (frame.program_counter >= frame.code.len) {
|
||||||
|
break :loop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -605,9 +635,11 @@ pub const Runtime = struct {
|
||||||
switch (function_type.parameters[i]) {
|
switch (function_type.parameters[i]) {
|
||||||
.val => |v| switch (v) {
|
.val => |v| switch (v) {
|
||||||
.i32 => {
|
.i32 => {
|
||||||
|
std.debug.print("Local with type i32\n", .{});
|
||||||
frame.locals[i] = .{ .i32 = @intCast(p) };
|
frame.locals[i] = .{ .i32 = @intCast(p) };
|
||||||
},
|
},
|
||||||
.i64 => {
|
.i64 => {
|
||||||
|
std.debug.print("Local with type i64\n", .{});
|
||||||
frame.locals[i] = .{ .i64 = @intCast(p) };
|
frame.locals[i] = .{ .i64 = @intCast(p) };
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
|
|
@ -620,9 +652,11 @@ pub const Runtime = struct {
|
||||||
switch (local) {
|
switch (local) {
|
||||||
.val => |v| switch (v) {
|
.val => |v| switch (v) {
|
||||||
.i32 => {
|
.i32 => {
|
||||||
|
std.debug.print("Local with type i32\n", .{});
|
||||||
frame.locals[i] = .{ .i32 = 0 };
|
frame.locals[i] = .{ .i32 = 0 };
|
||||||
},
|
},
|
||||||
.i64 => {
|
.i64 => {
|
||||||
|
std.debug.print("Local with type i64\n", .{});
|
||||||
frame.locals[i] = .{ .i64 = 0 };
|
frame.locals[i] = .{ .i64 = 0 };
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue