#!/usr/bin/awk -f # Constants BEGIN { IMAGE_SIZE = 524288 # Amount of simulated RAM DATA_DEPTH = 8192 # Depth of data stack ADDRESS_DEPTH = 32768 # Depth of the stacks # Initialize stacks data_sp = 0 addr_sp = 0 # VM state ip = 0 # Opcode definitions OP_NOP = 0 OP_LIT = 1 OP_DUP = 2 OP_DROP = 3 OP_SWAP = 4 OP_PUSH = 5 OP_POP = 6 OP_JUMP = 7 OP_CALL = 8 OP_CCALL = 9 OP_RETURN = 10 OP_EQ = 11 OP_NEQ = 12 OP_LT = 13 OP_GT = 14 OP_FETCH = 15 OP_STORE = 16 OP_ADD = 17 OP_SUB = 18 OP_MUL = 19 OP_DIVMOD = 20 OP_AND = 21 OP_OR = 22 OP_XOR = 23 OP_SHIFT = 24 OP_ZERO_EXIT = 25 OP_HALT = 26 OP_IE = 27 OP_IQ = 28 OP_II = 29 } # Stack operations function stack_push(stack_name, value) { if (stack_name == "data") { data_sp++ data_stack[data_sp] = value } else if (stack_name == "addr") { addr_sp++ addr_stack[addr_sp] = value } } function stack_pop(stack_name) { if (stack_name == "data") { if (data_sp > 0) { value = data_stack[data_sp] data_sp-- return value } } else if (stack_name == "addr") { if (addr_sp > 0) { value = addr_stack[addr_sp] addr_sp-- return value } } return 0 } function stack_tos(stack_name) { if (stack_name == "data" && data_sp > 0) { return data_stack[data_sp] } return 0 } function stack_nos(stack_name) { if (stack_name == "data" && data_sp > 1) { return data_stack[data_sp - 1] } return 0 } # Bitwise operation implementations function bitwise_and(x, y, i, result, a, b) { result = 0 for (i = 0; i < 32; i++) { a = int(x / (2 ^ i)) % 2 b = int(y / (2 ^ i)) % 2 if (a == 1 && b == 1) result += 2 ^ i } return result } function bitwise_or(x, y, i, result, a, b) { result = 0 for (i = 0; i < 32; i++) { a = int(x / (2 ^ i)) % 2 b = int(y / (2 ^ i)) % 2 if (a == 1 || b == 1) result += 2 ^ i } return result } function bitwise_xor(x, y, i, result, a, b) { result = 0 for (i = 0; i < 32; i++) { a = int(x / (2 ^ i)) % 2 b = int(y / (2 ^ i)) % 2 if (a != b) result += 2 ^ i } return result } function lshift(x, n) { return int(x * (2 ^ n)) } function rshift(x, n) { return int(x / (2 ^ n)) } # VM instruction implementations function process_opcode(opcode) { if (opcode == OP_NOP) { return } else if (opcode == OP_LIT) { ip++ stack_push("data", image[ip]) } else if (opcode == OP_DUP) { stack_push("data", stack_tos("data")) } else if (opcode == OP_DROP) { stack_pop("data") } else if (opcode == OP_SWAP) { temp = stack_pop("data") temp2 = stack_pop("data") stack_push("data", temp) stack_push("data", temp2) } else if (opcode == OP_PUSH) { stack_push("addr", stack_pop("data")) } else if (opcode == OP_POP) { stack_push("data", stack_pop("addr")) } else if (opcode == OP_JUMP) { ip = stack_pop("data") - 1 } else if (opcode == OP_CALL) { stack_push("addr", ip) ip = stack_pop("data") - 1 } else if (opcode == OP_CCALL) { a = stack_pop("data") b = stack_pop("data") if (b != 0) { stack_push("addr", ip) ip = a - 1 } } else if (opcode == OP_RETURN) { ip = stack_pop("addr") } else if (opcode == OP_EQ) { a = stack_pop("data") b = stack_pop("data") stack_push("data", (b == a) ? -1 : 0) } else if (opcode == OP_NEQ) { a = stack_pop("data") b = stack_pop("data") stack_push("data", (b != a) ? -1 : 0) } else if (opcode == OP_LT) { a = stack_pop("data") b = stack_pop("data") stack_push("data", (b < a) ? -1 : 0) } else if (opcode == OP_GT) { a = stack_pop("data") b = stack_pop("data") stack_push("data", (b > a) ? -1 : 0) } else if (opcode == OP_FETCH) { x = stack_pop("data") if (x == -1) stack_push("data", data_sp) else if (x == -2) stack_push("data", addr_sp) else if (x == -3) stack_push("data", IMAGE_SIZE) else if (x == -4) stack_push("data", -2147483648) else if (x == -5) stack_push("data", 2147483647) else stack_push("data", image[x]) } else if (opcode == OP_STORE) { addr = stack_pop("data") value = stack_pop("data") image[addr] = value } else if (opcode == OP_ADD) { x = stack_pop("data") y = stack_pop("data") stack_push("data", x + y) } else if (opcode == OP_SUB) { x = stack_pop("data") y = stack_pop("data") stack_push("data", y - x) } else if (opcode == OP_MUL) { x = stack_pop("data") y = stack_pop("data") stack_push("data", y * x) } else if (opcode == OP_DIVMOD) { b = stack_pop("data") a = stack_pop("data") if (b == 0) { ip = 0 data_sp = 0 addr_sp = 0 } else { x = abs(b) y = abs(a) q = int(y / x) r = y % x if (a < 0 && b < 0) r = r * -1 if (a > 0 && b < 0) q = q * -1 if (a < 0 && b > 0) { r = r * -1 q = q * -1 } stack_push("data", r) stack_push("data", q) } } else if (opcode == OP_AND) { x = stack_pop("data") y = stack_pop("data") stack_push("data", bitwise_and(x, y)) } else if (opcode == OP_OR) { x = stack_pop("data") y = stack_pop("data") stack_push("data", bitwise_or(x, y)) } else if (opcode == OP_XOR) { x = stack_pop("data") y = stack_pop("data") stack_push("data", bitwise_xor(x, y)) } else if (opcode == OP_SHIFT) { x = stack_pop("data") y = stack_pop("data") if (x < 0) stack_push("data", lshift(y, -x)) else stack_push("data", rshift(y, x)) } else if (opcode == OP_ZERO_EXIT) { if (stack_tos("data") == 0) { stack_pop("data") ip = stack_pop("addr") } } else if (opcode == OP_HALT) { ip = IMAGE_SIZE } check_stack() } # Helper functions function abs(x) { return x < 0 ? -x : x } function check_stack() { if (data_sp < 0 || addr_sp < 0 || data_sp > DATA_DEPTH || addr_sp > ADDRESS_DEPTH) { ip = 0 data_sp = 0 addr_sp = 0 } } function process_packed_opcodes(packed) { ops[0] = bitwise_and(packed, 255) ops[1] = bitwise_and(rshift(packed, 8), 255) ops[2] = bitwise_and(rshift(packed, 16), 255) ops[3] = bitwise_and(rshift(packed, 24), 255) for (i = 0; i < 4; i++) { if (ops[i] != 0) { process_opcode(ops[i]) } } } # Main execution function function execute(offset) { addr_sp = 1 ip = offset while (ip < IMAGE_SIZE) { opcode = image[ip] process_packed_opcodes(opcode) if (addr_sp == 0) ip = IMAGE_SIZE ip++ } } # String handling functions function string_inject(str, buffer, i, len) { len = length(str) for (i = 1; i <= len; i++) { image[buffer + i - 1] = ord(substr(str, i, 1)) image[buffer + i] = 0 } } function string_extract(at, str, i) { str = "" i = at while (image[i] != 0) { str = str chr(image[i]) i++ } return str } # Initialize VM BEGIN { prepare_vm() } function prepare_vm() { ip = 0 data_sp = 0 addr_sp = 0 }