about summary refs log blame commit diff stats
path: root/awk/retro/vm.awk
blob: cd894c5a5b4744f79119ccbff9a027ef13ffdd16 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<!DOCTYPE html>
<html dir="ltr" lang="en">
    <head>
        <meta charset='utf-8'>
        <title>System Development &amp; GDB</title>
    </head>
    <body>
        <a href="../index.html">Development Index</a>

        <h1>System Development</h1>

        <p>System development requires knowing how to debug
        kernel know how, in this example will be used Qemu
        and GDB. Qemu creates the virtual machine that kernel
        will run on and GDB will connect to it to help us
        understand how things tick.</p>

        <h2>Kernel Build</h2>

        <pre>
        $ tar xf linux-4.9.48.tar.xz
        $ cd linux-4.
#!/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
}