From 786901f108f50eedde9b8dad9c6d327b108b1276 Mon Sep 17 00:00:00 2001 From: elioat Date: Thu, 9 Jan 2025 20:30:45 -0500 Subject: * --- awk/retro/vm.awk | 364 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 364 insertions(+) create mode 100755 awk/retro/vm.awk (limited to 'awk/retro/vm.awk') diff --git a/awk/retro/vm.awk b/awk/retro/vm.awk new file mode 100755 index 0000000..cd894c5 --- /dev/null +++ b/awk/retro/vm.awk @@ -0,0 +1,364 @@ +#!/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 +} \ No newline at end of file -- cgit 1.4.1-2-gfad0