diff options
author | elioat <elioat@tilde.institute> | 2025-01-09 20:30:45 -0500 |
---|---|---|
committer | elioat <elioat@tilde.institute> | 2025-01-09 20:30:45 -0500 |
commit | 786901f108f50eedde9b8dad9c6d327b108b1276 (patch) | |
tree | 922951ec445b373dbe70987097e4988266ca6ced | |
parent | 662c3ceae2a4ffc598a8b99690a0cfdc0b4f47a8 (diff) | |
download | tour-786901f108f50eedde9b8dad9c6d327b108b1276.tar.gz |
*
-rwxr-xr-x | awk/retro/retro.awk | 250 | ||||
-rwxr-xr-x | awk/retro/test.awk | 52 | ||||
-rwxr-xr-x | awk/retro/vm.awk | 364 |
3 files changed, 666 insertions, 0 deletions
diff --git a/awk/retro/retro.awk b/awk/retro/retro.awk new file mode 100755 index 0000000..2a14ff0 --- /dev/null +++ b/awk/retro/retro.awk @@ -0,0 +1,250 @@ +#!/usr/bin/awk -f + +# Constants and VM setup +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 + + # Initialize VM + prepare_vm() + + # Load and run test program + load_test_program() + execute(0) + + # Print results + print "Stack contents after execution:" + print_stack() +} + +# 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 operations +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 +} + +# Helper functions +function abs(x) { + return x < 0 ? -x : x +} + +function lshift(x, n) { + return int(x * (2 ^ n)) +} + +function rshift(x, n) { + return int(x / (2 ^ n)) +} + +# VM core functions +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_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", x * y) + } + else if (opcode == OP_HALT) { + ip = IMAGE_SIZE + } +} + +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]) + } + } +} + +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++ + } +} + +function prepare_vm() { + ip = 0 + data_sp = 0 + addr_sp = 0 +} + +# Test program loader +function pack_opcodes(op1, op2, op3, op4) { + return op1 + (op2 * 256) + (op3 * 65536) + (op4 * 16777216) +} + +function load_test_program() { + # Simple test program that adds 10 and 5 + image[0] = pack_opcodes(OP_LIT, 0, 0, 0) # Push literal + image[1] = 10 # Value 10 + image[2] = pack_opcodes(OP_LIT, 0, 0, 0) # Push literal + image[3] = 5 # Value 5 + image[4] = pack_opcodes(OP_ADD, 0, 0, 0) # Add them + image[5] = pack_opcodes(OP_HALT, 0, 0, 0) # Halt +} + +# Debug helper +function print_stack() { + for (i = 1; i <= data_sp; i++) { + print "Item", i ":", data_stack[i] + } +} \ No newline at end of file diff --git a/awk/retro/test.awk b/awk/retro/test.awk new file mode 100755 index 0000000..191fa5b --- /dev/null +++ b/awk/retro/test.awk @@ -0,0 +1,52 @@ +#!/usr/bin/awk -f + +@include "vm.awk" + +# Complex test program +BEGIN { + # Test program to calculate factorial of 5 + i = 0 + + # Push 5 onto stack + image[i++] = pack_opcodes(OP_LIT, 0, 0, 0) + image[i++] = 5 + + # Push 1 onto stack (accumulator) + image[i++] = pack_opcodes(OP_LIT, 0, 0, 0) + image[i++] = 1 + + # Start of multiplication loop + loop_start = i + + # Duplicate top number (counter) + image[i++] = pack_opcodes(OP_DUP, 0, 0, 0) + + # Test if counter is zero + image[i++] = pack_opcodes(OP_ZERO_EXIT, 0, 0, 0) + + # Multiply accumulator by counter + image[i++] = pack_opcodes(OP_MUL, 0, 0, 0) + + # Decrement counter + image[i++] = pack_opcodes(OP_LIT, 0, 0, 0) + image[i++] = 1 + image[i++] = pack_opcodes(OP_SUB, 0, 0, 0) + + # Jump back to start of loop + image[i++] = pack_opcodes(OP_LIT, 0, 0, 0) + image[i++] = loop_start + image[i++] = pack_opcodes(OP_JUMP, 0, 0, 0) + + # Halt + image[i++] = pack_opcodes(OP_HALT, 0, 0, 0) + + # Execute program + execute(0) + + # Print result (should be 120 - factorial of 5) + print "Factorial of 5:", stack_tos("data") +} + +function pack_opcodes(op1, op2, op3, op4) { + return op1 + (op2 * 256) + (op3 * 65536) + (op4 * 16777216) +} \ No newline at end of file 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 |